/*
* Copyright (c) 2026 blueloveTH
* Distributed Under The MIT License
* https://github.com/pocketpy/pocketpy
*/
#define PK_IS_AMALGAMATED_C
#include "pocketpy.h"
// common/_generated.h
// generated by prebuild.py
const char* load_kPythonLib(const char* name);
extern const char kPythonLibs_bisect[];
extern const char kPythonLibs_builtins[];
extern const char kPythonLibs_cmath[];
extern const char kPythonLibs_collections[];
extern const char kPythonLibs_dataclasses[];
extern const char kPythonLibs_datetime[];
extern const char kPythonLibs_functools[];
extern const char kPythonLibs_heapq[];
extern const char kPythonLibs_linalg[];
extern const char kPythonLibs_operator[];
extern const char kPythonLibs_typing[];
// common/_log_spline_tbl.h
/*
Copyright (c) 2012,2013 Axel Kohlmeyer <akohlmey@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static const double fm_log_dinv = 4.09600000000000000000e+03;
static const double fm_log_dsq6 = 9.93410746256510361521e-09;
static const double fm_log_q1[] = {
0.00000000000000000000e+00, 2.44110827527362707389e-04,
4.88162079501351187181e-04, 7.32153784993847520958e-04,
9.76085973055458924752e-04, 1.21995867271553880967e-03,
1.46377191298220740885e-03, 1.70752572284237243150e-03,
1.95122013126174933748e-03, 2.19485516718488302135e-03,
2.43843085953516754485e-03, 2.68194723721486717044e-03,
2.92540432910513587689e-03, 3.16880216406604034440e-03,
3.41214077093657773554e-03, 3.65542017853469781291e-03,
3.89864041565732288852e-03, 4.14180151108036864044e-03,
4.38490349355876492948e-03, 4.62794639182647314646e-03,
4.87093023459651223300e-03, 5.11385505056097429410e-03,
5.35672086839104454742e-03, 5.59952771673702821148e-03,
5.84227562422836091405e-03, 6.08496461947363731504e-03,
6.32759473106062758641e-03, 6.57016598755629822881e-03,
6.81267841750683115359e-03, 7.05513204943764623417e-03,
7.29752691185341952063e-03, 7.53986303323810405641e-03,
7.78214044205494896028e-03, 8.02435916674652111036e-03,
8.26651923573472682816e-03, 8.50862067742082402166e-03,
8.75066352018545254299e-03, 8.99264779238864719879e-03,
9.23457352236985856697e-03, 9.47644073844797554806e-03,
9.71824946892134618193e-03, 9.95999974206778979080e-03,
1.02016915861446264696e-02, 1.04433250293886909638e-02,
1.06849001000163534858e-02, 1.09264168262235422668e-02,
1.11678752361857574343e-02, 1.14092753580580970330e-02,
1.16506172199752743718e-02, 1.18919008500516353716e-02,
1.21331262763811845856e-02, 1.23742935270375938733e-02,
1.26154026300742353600e-02, 1.28564536135241883757e-02,
1.30974465054002689457e-02, 1.33383813336950454026e-02,
1.35792581263808539993e-02, 1.38200769114098266643e-02,
1.40608377167139014102e-02, 1.43015405702048535586e-02,
1.45421854997742992094e-02, 1.47827725332937282010e-02,
1.50233016986145197225e-02, 1.52637730235679579260e-02,
1.55041865359652544787e-02, 1.57445422635975676440e-02,
1.59848402342360230988e-02, 1.62250804756317243416e-02,
1.64652630155157908565e-02, 1.67053878815993511742e-02,
1.69454551015735914443e-02, 1.71854647031097450272e-02,
1.74254167138591341268e-02, 1.76653111614531801998e-02,
1.79051480735034213021e-02, 1.81449274776015329058e-02,
1.83846494013193521855e-02, 1.86243138722088884263e-02,
1.88639209178023438407e-02, 1.91034705656121447936e-02,
1.93429628431309348635e-02, 1.95823977778316234144e-02,
1.98217753971673821267e-02, 2.00610957285716796916e-02,
2.03003587994582852805e-02, 2.05395646372212997699e-02,
2.07787132692351730889e-02, 2.10178047228547111580e-02,
2.12568390254151175223e-02, 2.14958162042319829432e-02,
2.17347362866013270322e-02, 2.19735992997996155973e-02,
2.22124052710837606439e-02, 2.24511542276911585381e-02,
2.26898461968397004151e-02, 2.29284812057277964659e-02,
2.31670592815343794058e-02, 2.34055804514189426391e-02,
2.36440447425215437283e-02, 2.38824521819628390884e-02,
2.41208027968440805178e-02, 2.43590966142471533618e-02,
2.45973336612345834518e-02, 2.48355139648495648608e-02,
2.50736375521159599034e-02, 2.53117044500383477079e-02,
2.55497146856020138084e-02, 2.57876682857729813692e-02,
2.60255652774980320019e-02, 2.62634056877047161738e-02,
2.65011895433013774936e-02, 2.67389168711771700593e-02,
2.69765876982020758046e-02, 2.72142020512269183774e-02,
2.74517599570833874256e-02, 2.76892614425840594139e-02,
2.79267065345224080319e-02, 2.81640952596728215418e-02,
2.84014276447906305334e-02, 2.86387037166121183329e-02,
2.88759235018545418194e-02, 2.91130870272161487722e-02,
2.93501943193761917483e-02, 2.95872454049949593080e-02,
2.98242403107137760143e-02, 3.00611790631550336583e-02,
3.02980616889222051369e-02, 3.05348882145998617998e-02,
3.07716586667536873279e-02, 3.10083730719305089574e-02,
3.12450314566582974807e-02, 3.14816338474461984709e-02,
3.17181802707845392209e-02, 3.19546707531448703765e-02,
3.21911053209799416508e-02, 3.24274840007237608042e-02,
3.26638068187915936447e-02, 3.29000738015799848446e-02,
3.31362849754667510016e-02, 3.33724403668110569665e-02,
3.36085400019533672711e-02, 3.38445839072155085780e-02,
3.40805721089006696811e-02, 3.43165046332934153828e-02,
3.45523815066597350665e-02, 3.47882027552470010634e-02,
3.50239684052840449802e-02, 3.52596784829811438211e-02,
3.54953330145300408049e-02, 3.57309320261039800593e-02,
3.59664755438576927427e-02, 3.62019635939274456171e-02,
3.64373962024310479868e-02, 3.66727733954678516981e-02,
3.69080951991187997119e-02, 3.71433616394464122257e-02,
3.73785727424948352460e-02, 3.76137285342898197715e-02,
3.78488290408387842434e-02, 3.80838742881307937282e-02,
3.83188643021366015518e-02, 3.85537991088086354208e-02,
3.87886787340810668123e-02, 3.90235032038697762791e-02,
3.92582725440723950827e-02, 3.94929867805683190718e-02,
3.97276459392187364372e-02, 3.99622500458666138345e-02,
4.01967991263367518950e-02, 4.04312932064357782869e-02,
4.06657323119521615928e-02, 4.09001164686562529438e-02,
4.11344457023002721408e-02, 4.13687200386183492884e-02,
4.16029395033265247950e-02, 4.18371041221227840667e-02,
4.20712139206870575081e-02, 4.23052689246812343993e-02,
4.25392691597492184075e-02, 4.27732146515168790146e-02,
4.30071054255921278453e-02, 4.32409415075649117277e-02,
4.34747229230072265715e-02, 4.37084496974731243069e-02,
4.39421218564987614563e-02, 4.41757394256023921963e-02,
4.44093024302843961126e-02, 4.46428108960272643224e-02,
4.48762648482956758023e-02, 4.51096643125364488158e-02,
4.53430093141786172417e-02, 4.55762998786333820012e-02,
4.58095360312942012637e-02, 4.60427177975367488139e-02,
4.62758452027189418065e-02, 4.65089182721809893395e-02,
4.67419370312453785754e-02, 4.69749015052168886197e-02,
4.72078117193826252151e-02, 4.74406676990120346193e-02,
4.76734694693569036050e-02, 4.79062170556513941544e-02,
4.81389104831120573369e-02, 4.83715497769378263704e-02,
4.86041349623100790711e-02, 4.88366660643926031593e-02,
4.90691431083316448314e-02, 4.93015661192559226378e-02,
4.95339351222766274829e-02, 4.97662501424874642586e-02,
4.99985112049646240884e-02, 5.02307183347668675943e-02,
5.04628715569354693860e-02, 5.06949708964942874490e-02,
5.09270163784497562065e-02, 5.11590080277909073359e-02,
5.13909458694893697683e-02, 5.16228299284994252005e-02,
5.18546602297579733998e-02, 5.20864367981846085320e-02,
5.23181596586815636507e-02, 5.25498288361337939634e-02,
5.27814443554089490762e-02, 5.30130062413574076885e-02,
5.32445145188122845314e-02, 5.34759692125894581238e-02,
5.37073703474875707720e-02, 5.39387179482880632642e-02,
5.41700120397551818097e-02, 5.44012526466359849775e-02,
5.46324397936603645132e-02, 5.48635735055410730943e-02,
5.50946538069737382082e-02, 5.53256807226368482744e-02,
5.55566542771918150945e-02, 5.57875744952829599743e-02,
5.60184414015375206630e-02, 5.62492550205656929863e-02,
5.64800153769606447240e-02, 5.67107224952985156108e-02,
5.69413764001384242741e-02, 5.71719771160225237461e-02,
5.74025246674759737076e-02, 5.76330190790069890605e-02,
5.78634603751068329891e-02, 5.80938485802498377764e-02,
5.83241837188934394987e-02, 5.85544658154781641479e-02,
5.87846948944276553872e-02, 5.90148709801487023063e-02,
5.92449940970312324828e-02, 5.94750642694483605544e-02,
5.97050815217563465853e-02, 5.99350458782946862724e-02,
6.01649573633860623723e-02, 6.03948160013363932741e-02,
6.06246218164348399382e-02, 6.08543748329538267128e-02,
6.10840750751490343951e-02, 6.13137225672594557424e-02,
6.15433173335073746557e-02, 6.17728593980984008738e-02,
6.20023487852214699734e-02, 6.22317855190488850026e-02,
6.24611696237362887252e-02, 6.26905011234227399486e-02,
6.29197800422306580126e-02, 6.31490064042658921784e-02,
6.33781802336177285673e-02, 6.36073015543588693443e-02,
6.38363703905454882293e-02, 6.40653867662172443742e-02,
6.42943507053972546084e-02, 6.45232622320921628267e-02,
6.47521213702921261124e-02, 6.49809281439708147365e-02,
6.52096825770854676696e-02, 6.54383846935768787034e-02,
6.56670345173694380847e-02, 6.58956320723710908815e-02,
6.61241773824734202503e-02, 6.63526704715516196798e-02,
6.65811113634645346249e-02, 6.68095000820546486286e-02,
6.70378366511480972001e-02, 6.72661210945547510809e-02,
6.74943534360681191009e-02, 6.77225336994654592004e-02,
6.79506619085077506748e-02, 6.81787380869397080518e-02,
6.84067622584897949700e-02, 6.86347344468702658116e-02,
6.88626546757771518248e-02, 6.90905229688902888796e-02,
6.93183393498733174676e-02, 6.95461038423737382130e-02,
6.97738164700228424842e-02, 7.00014772564358511708e-02,
7.02290862252118036624e-02, 7.04566433999336549920e-02,
7.06841488041682619592e-02, 7.09116024614664108849e-02,
7.11390043953627759787e-02, 7.13663546293760442385e-02,
7.15936531870088183060e-02, 7.18209000917476997339e-02,
7.20480953670632612296e-02, 7.22752390364101160447e-02,
7.25023311232268624638e-02, 7.27293716509361670708e-02,
7.29563606429447231161e-02, 7.31832981226432782718e-02,
7.34101841134067040207e-02, 7.36370186385939123896e-02,
7.38638017215479669719e-02, 7.40905333855960135381e-02,
7.43172136540493771806e-02, 7.45438425502034929249e-02,
7.47704200973380028739e-02, 7.49969463187166729412e-02,
7.52234212375875316292e-02, 7.54498448771827451287e-02,
7.56762172607187699747e-02, 7.59025384113962420241e-02,
7.61288083524001013558e-02, 7.63550271068994951262e-02,
7.65811946980478885916e-02, 7.68073111489830512300e-02,
7.70333764828270151082e-02, 7.72593907226861720261e-02,
7.74853538916512596391e-02, 7.77112660127973059465e-02,
7.79371271091837819478e-02, 7.81629372038544767420e-02,
7.83886963198376085504e-02, 7.86144044801457830829e-02,
7.88400617077760212936e-02, 7.90656680257098148923e-02,
7.92912234569130569550e-02, 7.95167280243361529468e-02,
7.97421817509139374547e-02, 7.99675846595657713323e-02,
8.01929367731955139442e-02, 8.04182381146915231662e-02,
8.06434887069267247739e-02, 8.08686885727585569317e-02,
8.10938377350290395817e-02, 8.13189362165647605662e-02,
8.15439840401769033829e-02, 8.17689812286612333070e-02,
8.19939278047981806585e-02, 8.22188237913527297795e-02,
8.24436692110745855677e-02, 8.26684640866980763318e-02,
8.28932084409421815474e-02, 8.31179022965106151233e-02,
8.33425456760917421350e-02, 8.35671386023586620917e-02,
8.37916810979692228134e-02, 8.40161731855659649204e-02,
8.42406148877762328553e-02, 8.44650062272121054940e-02,
8.46893472264704516572e-02, 8.49136379081329439877e-02,
8.51378782947660450731e-02, 8.53620684089210490786e-02,
8.55862082731341095032e-02, 8.58102979099261975460e-02,
8.60343373418031576172e-02, 8.62583265912557073385e-02,
8.64822656807594791761e-02, 8.67061546327749649299e-02,
8.69299934697476128775e-02, 8.71537822141077861415e-02,
8.73775208882708043223e-02, 8.76012095146369157428e-02,
8.78248481155913807150e-02, 8.80484367135044021513e-02,
8.82719753307312088308e-02, 8.84954639896120276443e-02,
8.87189027124721391049e-02, 8.89422915216218218371e-02,
8.91656304393564219657e-02, 8.93889194879563669938e-02,
8.96121586896871380468e-02, 8.98353480667993115061e-02,
9.00584876415286006424e-02, 9.02815774360957862266e-02,
9.05046174727068136745e-02, 9.07276077735527791690e-02,
9.09505483608099157822e-02, 9.11734392566396351087e-02,
9.13962804831885272661e-02, 9.16190720625884025274e-02,
9.18418140169562635666e-02, 9.20645063683943332133e-02,
9.22871491389900822089e-02, 9.25097423508162430839e-02,
9.27322860259307685249e-02, 9.29547801863769285191e-02,
9.31772248541832964763e-02, 9.33996200513636798402e-02,
9.36219657999172727436e-02, 9.38442621218285727425e-02,
9.40665090390674085707e-02, 9.42887065735889817741e-02,
9.45108547473338389544e-02, 9.47329535822279272805e-02,
9.49550031001825944887e-02, 9.51770033230945750047e-02,
9.53989542728460315768e-02, 9.56208559713045552764e-02,
9.58427084403232071308e-02, 9.60645117017404626125e-02,
9.62862657773803226613e-02, 9.65079706890522165397e-02,
9.67296264585511128553e-02, 9.69512331076574779276e-02,
9.71727906581372896655e-02, 9.73942991317420792008e-02,
9.76157585502089170104e-02, 9.78371689352604545498e-02,
9.80585303086048687415e-02, 9.82798426919359729981e-02,
9.85011061069331617102e-02, 9.87223205752614380026e-02,
9.89434861185714414900e-02, 9.91646027584994482762e-02,
9.93856705166673570773e-02, 9.96066894146827863654e-02,
9.98276594741389772247e-02, 1.00048580716614876618e-01,
1.00269453163675151264e-01, 1.00490276836870159882e-01,
1.00711051757735994827e-01, 1.00931777947794482087e-01,
1.01152455428553222916e-01, 1.01373084221505552205e-01,
1.01593664348130593988e-01, 1.01814195829893261447e-01,
1.02034678688244284661e-01, 1.02255112944620182858e-01,
1.02475498620443319919e-01, 1.02695835737121890507e-01,
1.02916124316049961696e-01, 1.03136364378607417458e-01,
1.03356555946160069692e-01, 1.03576699040059588830e-01,
1.03796793681643559348e-01, 1.04016839892235493648e-01,
1.04236837693144804295e-01, 1.04456787105666845661e-01,
1.04676688151082941669e-01, 1.04896540850660371924e-01,
1.05116345225652385587e-01, 1.05336101297298229129e-01,
1.05555809086823132459e-01, 1.05775468615438378306e-01,
1.05995079904341218957e-01, 1.06214642974714987278e-01,
1.06434157847729041202e-01, 1.06653624544538833119e-01,
1.06873043086285854364e-01, 1.07092413494097690729e-01,
1.07311735789088050219e-01, 1.07531009992356721416e-01,
1.07750236124989628994e-01, 1.07969414208058833715e-01,
1.08188544262622546310e-01, 1.08407626309725127478e-01,
1.08626660370397129518e-01, 1.08845646465655254698e-01,
1.09064584616502438519e-01, 1.09283474843927794207e-01,
1.09502317168906668221e-01, 1.09721111612400654134e-01,
1.09939858195357564874e-01, 1.10158556938711474360e-01,
1.10377207863382731379e-01, 1.10595810990277973462e-01,
1.10814366340290113011e-01, 1.11032873934298378926e-01,
1.11251333793168288855e-01, 1.11469745937751746334e-01,
1.11688110388886929769e-01, 1.11906427167398417333e-01,
1.12124696294097117577e-01, 1.12342917789780338822e-01,
1.12561091675231775278e-01, 1.12779217971221507044e-01,
1.12997296698506041746e-01, 1.13215327877828272896e-01,
1.13433311529917590921e-01, 1.13651247675489786015e-01,
1.13869136335247131409e-01, 1.14086977529878327853e-01,
1.14304771280058628524e-01, 1.14522517606449728000e-01,
1.14740216529699845527e-01, 1.14957868070443711139e-01,
1.15175472249302593419e-01, 1.15393029086884285617e-01,
1.15610538603783147282e-01, 1.15828000820580104269e-01,
1.16045415757842648730e-01, 1.16262783436124880754e-01,
1.16480103875967480609e-01, 1.16697377097897722620e-01,
1.16914603122429544557e-01, 1.17131781970063506004e-01,
1.17348913661286788357e-01, 1.17565998216573264212e-01,
1.17783035656383455736e-01, 1.18000026001164562417e-01,
1.18216969271350488824e-01, 1.18433865487361844604e-01,
1.18650714669605930607e-01, 1.18867516838476808272e-01,
1.19084272014355257996e-01, 1.19300980217608820766e-01,
1.19517641468591770404e-01, 1.19734255787645210711e-01,
1.19950823195096950569e-01, 1.20167343711261670469e-01,
1.20383817356440825375e-01, 1.20600244150922672470e-01,
1.20816624114982326677e-01, 1.21032957268881732893e-01,
1.21249243632869679876e-01, 1.21465483227181855752e-01,
1.21681676072040778624e-01, 1.21897822187655879844e-01,
1.22113921594223476252e-01, 1.22329974311926811814e-01,
1.22545980360936043740e-01, 1.22761939761408242489e-01,
1.22977852533487461151e-01, 1.23193718697304666065e-01,
1.23409538272977806206e-01, 1.23625311280611813181e-01,
1.23841037740298615111e-01, 1.24056717672117122753e-01,
1.24272351096133243376e-01, 1.24487938032399964028e-01,
1.24703478500957240516e-01, 1.24918972521832094547e-01,
1.25134420115038641486e-01, 1.25349821300578007088e-01,
1.25565176098438396890e-01, 1.25780484528595165594e-01,
1.25995746611010733806e-01, 1.26210962365634615789e-01,
1.26426131812403447219e-01, 1.26641254971241012939e-01,
1.26856331862058274718e-01, 1.27071362504753287981e-01,
1.27286346919211340589e-01, 1.27501285125304814061e-01,
1.27716177142893322349e-01, 1.27931022991823739599e-01,
1.28145822691930033610e-01, 1.28360576263033487887e-01,
1.28575283724942590613e-01, 1.28789945097453034650e-01,
1.29004560400347856319e-01, 1.29219129653397241109e-01,
1.29433652876358717965e-01, 1.29648130088977159291e-01,
1.29862561310984586660e-01, 1.30076946562100476124e-01,
1.30291285862031563925e-01, 1.30505579230471902008e-01,
1.30719826687102885776e-01, 1.30934028251593309600e-01,
1.31148183943599283552e-01, 1.31362293782764316674e-01,
1.31576357788719261466e-01, 1.31790375981082452661e-01,
1.32004348379459540697e-01, 1.32218275003443658244e-01,
1.32432155872615309189e-01, 1.32645991006542507407e-01,
1.32859780424780610231e-01, 1.33073524146872568252e-01,
1.33287222192348703276e-01, 1.33500874580726874852e-01,
1.33714481331512369255e-01, 1.33928042464198038264e-01,
1.34141557998264243645e-01, 1.34355027953178857159e-01,
1.34568452348397260554e-01, 1.34781831203362401084e-01,
1.34995164537504819258e-01, 1.35208452370242593332e-01,
1.35421694720981339310e-01, 1.35634891609114321964e-01,
1.35848043054022371567e-01, 1.36061149075073939407e-01,
1.36274209691625097784e-01, 1.36487224923019567768e-01,
1.36700194788588663686e-01, 1.36913119307651376388e-01,
1.37125998499514401008e-01, 1.37338832383471998178e-01,
1.37551620978806243834e-01, 1.37764364304786807169e-01,
1.37977062380671117170e-01, 1.38189715225704279344e-01,
1.38402322859119131238e-01, 1.38614885300136297941e-01,
1.38827402567964081070e-01, 1.39039874681798569789e-01,
1.39252301660823613050e-01, 1.39464683524210875110e-01,
1.39677020291119724504e-01, 1.39889311980697400584e-01,
1.40101558612078930244e-01, 1.40313760204387127928e-01,
1.40525916776732706648e-01, 1.40738028348214166963e-01,
1.40950094937917824733e-01, 1.41162116564917949901e-01,
1.41374093248276627710e-01, 1.41586025007043814217e-01,
1.41797911860257336292e-01, 1.42009753826943030397e-01,
1.42221550926114520541e-01, 1.42433303176773412568e-01,
1.42645010597909210892e-01, 1.42856673208499401762e-01,
1.43068291027509425506e-01, 1.43279864073892648779e-01,
1.43491392366590420071e-01, 1.43702875924532069707e-01,
1.43914314766634937603e-01, 1.44125708911804373269e-01,
1.44337058378933680292e-01, 1.44548363186904282873e-01,
1.44759623354585531541e-01, 1.44970838900834897434e-01,
1.45182009844497889040e-01, 1.45393136204408079948e-01,
1.45604217999387053339e-01, 1.45815255248244596276e-01,
1.46026247969778477653e-01, 1.46237196182774614739e-01,
1.46448099906007073168e-01, 1.46658959158237983678e-01,
1.46869773958217680887e-01, 1.47080544324684536761e-01,
1.47291270276365154901e-01, 1.47501951831974315033e-01,
1.47712589010214945251e-01, 1.47923181829778122021e-01,
1.48133730309343181197e-01, 1.48344234467577607006e-01,
1.48554694323137143064e-01, 1.48765109894665709112e-01,
1.48975481200795512038e-01, 1.49185808260146962612e-01,
1.49396091091328730993e-01, 1.49606329712937774490e-01,
1.49816524143559282045e-01, 1.50026674401766757505e-01,
1.50236780506121964107e-01, 1.50446842475175063258e-01,
1.50656860327464364735e-01, 1.50866834081516687505e-01,
1.51076763755846998905e-01, 1.51286649368958775463e-01,
1.51496490939343725346e-01, 1.51706288485481954886e-01,
1.51916042025841968588e-01, 1.52125751578880641368e-01,
1.52335417163043190802e-01, 1.52545038796763288147e-01,
1.52754616498463030583e-01, 1.52964150286552857949e-01,
1.53173640179431691521e-01, 1.53383086195486906256e-01,
1.53592488353094303033e-01, 1.53801846670618136415e-01,
1.54011161166411142398e-01, 1.54220431858814510662e-01,
1.54429658766157940075e-01, 1.54638841906759666456e-01,
1.54847981298926323790e-01, 1.55057076960953166278e-01,
1.55266128911123957312e-01, 1.55475137167710913966e-01,
1.55684101748974929036e-01, 1.55893022673165321246e-01,
1.56101899958520057288e-01, 1.56310733623265640801e-01,
1.56519523685617195641e-01, 1.56728270163778410362e-01,
1.56936973075941565980e-01, 1.57145632440287563725e-01,
1.57354248274985952794e-01, 1.57562820598194874844e-01,
1.57771349428061147258e-01, 1.57979834782720207631e-01,
1.58188276680296169285e-01, 1.58396675138901821267e-01,
1.58605030176638572836e-01, 1.58813341811596647757e-01,
1.59021610061854806739e-01, 1.59229834945480652753e-01,
1.59438016480530436736e-01, 1.59646154685049140864e-01,
1.59854249577070506305e-01, 1.60062301174616977706e-01,
1.60270309495699786462e-01, 1.60478274558318922960e-01,
1.60686196380463164335e-01, 1.60894074980109991202e-01,
1.61101910375225781946e-01, 1.61309702583765646189e-01,
1.61517451623673535810e-01, 1.61725157512882217192e-01,
1.61932820269313243466e-01, 1.62140439910877065532e-01,
1.62348016455472948794e-01, 1.62555549920989028667e-01,
1.62763040325302282829e-01, 1.62970487686278558970e-01,
1.63177892021772658060e-01, 1.63385253349628167818e-01,
1.63592571687677657000e-01, 1.63799847053742592129e-01,
1.64007079465633337501e-01, 1.64214268941149182934e-01,
1.64421415498078399287e-01, 1.64628519154198182939e-01,
1.64835579927274655798e-01, 1.65042597835062948564e-01,
1.65249572895307172971e-01, 1.65456505125740366280e-01,
1.65663394544084602300e-01, 1.65870241168050991387e-01,
1.66077045015339569423e-01, 1.66283806103639492102e-01,
1.66490524450628840647e-01, 1.66697200073974843848e-01,
1.66903832991333683777e-01, 1.67110423220350634566e-01,
1.67316970778660090158e-01, 1.67523475683885425536e-01,
1.67729937953639163251e-01, 1.67936357605522890157e-01,
1.68142734657127340681e-01, 1.68349069126032285793e-01,
1.68555361029806671791e-01, 1.68761610386008564788e-01,
1.68967817212185178466e-01, 1.69173981525872818565e-01,
1.69380103344597049420e-01, 1.69586182685872471909e-01,
1.69792219567202973263e-01, 1.69998214006081560523e-01,
1.70204166019990471570e-01, 1.70410075626401119608e-01,
1.70615942842774093169e-01, 1.70821767686559267130e-01,
1.71027550175195747206e-01, 1.71233290326111786683e-01,
1.71438988156724952949e-01, 1.71644643684442071985e-01,
1.71850256926659228363e-01, 1.72055827900761737492e-01,
1.72261356624124201131e-01, 1.72466843114110590651e-01,
1.72672287388074080505e-01, 1.72877689463357187005e-01,
1.73083049357291768322e-01, 1.73288367087198941219e-01,
1.73493642670389247584e-01, 1.73698876124162460144e-01,
1.73904067465807832260e-01, 1.74109216712603848132e-01,
1.74314323881818417084e-01, 1.74519388990708873566e-01,
1.74724412056521866132e-01, 1.74929393096493468462e-01,
1.75134332127849151606e-01, 1.75339229167803783982e-01,
1.75544084233561659136e-01, 1.75748897342316551251e-01,
1.75953668511251576367e-01, 1.76158397757539414430e-01,
1.76363085098342059487e-01, 1.76567730550811097245e-01,
1.76772334132087538539e-01, 1.76976895859301847080e-01,
1.77181415749573994978e-01, 1.77385893820013462729e-01,
1.77590330087719266983e-01, 1.77794724569779849510e-01,
1.77999077283273271499e-01, 1.78203388245267047019e-01,
1.78407657472818309552e-01, 1.78611884982973673219e-01,
1.78816070792769343800e-01, 1.79020214919231090978e-01,
1.79224317379374276094e-01, 1.79428378190203796638e-01,
1.79632397368714169517e-01, 1.79836374931889531048e-01,
1.80040310896703609211e-01, 1.80244205280119751400e-01,
1.80448058099090896667e-01, 1.80651869370559686745e-01,
1.80855639111458355028e-01, 1.81059367338708782080e-01,
1.81263054069222551146e-01, 1.81466699319900892640e-01,
1.81670303107634684148e-01, 1.81873865449304533692e-01,
1.82077386361780724222e-01, 1.82280865861923213611e-01,
1.82484303966581717926e-01, 1.82687700692595655916e-01,
1.82891056056794149010e-01, 1.83094370075996104585e-01,
1.83297642767010077192e-01, 1.83500874146634490591e-01,
1.83704064231657471229e-01, 1.83907213038856875986e-01,
1.84110320585000403204e-01, 1.84313386886845537171e-01,
1.84516411961139520370e-01, 1.84719395824619381230e-01,
1.84922338494011989640e-01, 1.85125239986034056949e-01,
1.85328100317392080454e-01, 1.85530919504782398910e-01,
1.85733697564891192533e-01, 1.85936434514394538509e-01,
1.86139130369958299971e-01, 1.86341785148238237024e-01,
1.86544398865880034499e-01, 1.86746971539519163175e-01,
1.86949503185781101822e-01, 1.87151993821281115160e-01,
1.87354443462624475902e-01, 1.87556852126406298220e-01,
1.87759219829211676522e-01, 1.87961546587615574433e-01,
1.88163832418182991324e-01, 1.88366077337468768027e-01,
1.88568281362017808878e-01, 1.88770444508364887426e-01,
1.88972566793034812971e-01, 1.89174648232542347293e-01,
1.89376688843392260164e-01, 1.89578688642079329352e-01,
1.89780647645088312858e-01, 1.89982565868893976679e-01,
1.90184443329961150315e-01, 1.90386280044744643503e-01,
1.90588076029689357238e-01, 1.90789831301230172755e-01,
1.90991545875792090303e-01, 1.91193219769790145879e-01,
1.91394852999629466739e-01, 1.91596445581705188133e-01,
1.91797997532402592080e-01, 1.91999508868097079617e-01,
1.92200979605154115282e-01, 1.92402409759929254873e-01,
1.92603799348768200961e-01, 1.92805148388006802884e-01,
1.93006456893970973487e-01, 1.93207724882976855652e-01,
1.93408952371330711273e-01, 1.93610139375328893507e-01,
1.93811285911258013304e-01, 1.94012391995394828381e-01,
1.94213457644006270986e-01, 1.94414482873349420133e-01,
1.94615467699671668145e-01, 1.94816412139210470844e-01,
1.95017316208193597360e-01, 1.95218179922839019103e-01,
1.95419003299354882008e-01, 1.95619786353939673074e-01,
1.95820529102782026065e-01, 1.96021231562060860298e-01,
1.96221893747945352882e-01, 1.96422515676594994227e-01,
1.96623097364159477030e-01, 1.96823638826778835043e-01,
1.97024140080583359813e-01, 1.97224601141693656192e-01,
1.97425022026220642335e-01, 1.97625402750265521945e-01,
1.97825743329919867541e-01, 1.98026043781265564947e-01,
1.98226304120374813289e-01, 1.98426524363310180510e-01,
1.98626704526124575612e-01, 1.98826844624861304167e-01,
1.99026944675553985054e-01, 1.99227004694226633719e-01,
1.99427024696893717692e-01, 1.99627004699559990053e-01,
1.99826944718220655961e-01, 2.00026844768861317148e-01,
2.00226704867458055181e-01, 2.00426525029977237180e-01,
2.00626305272375821120e-01, 2.00826045610601050528e-01,
2.01025746060590732034e-01, 2.01225406638273096593e-01,
2.01425027359566771734e-01, 2.01624608240380948088e-01,
2.01824149296615212856e-01, 2.02023650544159688591e-01,
2.02223111998894977681e-01, 2.02422533676692190108e-01,
2.02621915593412915690e-01, 2.02821257764909251842e-01,
2.03020560207023886834e-01, 2.03219822935589961022e-01,
2.03419045966431177863e-01, 2.03618229315361776166e-01,
2.03817372998186613353e-01, 2.04016477030700998929e-01,
2.04215541428690888770e-01, 2.04414566207932774100e-01,
2.04613551384193764759e-01, 2.04812496973231533692e-01,
2.05011402990794316947e-01, 2.05210269452621052455e-01,
2.05409096374441185739e-01, 2.05607883771974836451e-01,
2.05806631660932742856e-01, 2.06005340057016289590e-01,
2.06204008975917452151e-01, 2.06402638433318963429e-01,
2.06601228444894063907e-01, 2.06799779026306806973e-01,
2.06998290193211781363e-01, 2.07196761961254388718e-01,
2.07395194346070593783e-01, 2.07593587363287118697e-01,
2.07791941028521415236e-01, 2.07990255357381581547e-01,
2.08188530365466473171e-01, 2.08386766068365619775e-01,
2.08584962481659336175e-01, 2.08783119620918666826e-01,
2.08981237501705385817e-01, 2.09179316139571996880e-01,
2.09377355550061788891e-01, 2.09575355748708863635e-01,
2.09773316751038024774e-01, 2.09971238572564861125e-01,
2.10169121228795829914e-01, 2.10366964735228090255e-01,
2.10564769107349641919e-01, 2.10762534360639325337e-01,
2.10960260510566738335e-01, 2.11157947572592374907e-01,
2.11355595562167514201e-01, 2.11553204494734276020e-01,
2.11750774385725648585e-01, 2.11948305250565460778e-01,
2.12145797104668409894e-01, 2.12343249963440033889e-01,
2.12540663842276822404e-01, 2.12738038756566050225e-01,
2.12935374721685971577e-01, 2.13132671753005653592e-01,
2.13329929865885142837e-01, 2.13527149075675354295e-01,
2.13724329397718126877e-01, 2.13921470847346278932e-01,
2.14118573439883469467e-01, 2.14315637190644364685e-01,
2.14512662114934554713e-01, 2.14709648228050609120e-01,
2.14906595545280021398e-01, 2.15103504081901292233e-01,
2.15300373853183873996e-01, 2.15497204874388170737e-01,
2.15693997160765676968e-01, 2.15890750727558783373e-01,
2.16087465590000943338e-01, 2.16284141763316617446e-01,
2.16480779262721245715e-01, 2.16677378103421303113e-01,
2.16873938300614355068e-01, 2.17070459869488946447e-01,
2.17266942825224712577e-01, 2.17463387182992295976e-01,
2.17659792957953429626e-01, 2.17856160165260909212e-01,
2.18052488820058593122e-01, 2.18248778937481485718e-01,
2.18445030532655570799e-01, 2.18641243620698005889e-01,
2.18837418216717038977e-01, 2.19033554335812036262e-01,
2.19229651993073426652e-01, 2.19425711203582840536e-01,
2.19621731982412998763e-01, 2.19817714344627740397e-01,
2.20013658305282105987e-01, 2.20209563879422226540e-01,
2.20405431082085434547e-01, 2.20601259928300208468e-01,
2.20797050433086200494e-01, 2.20992802611454264294e-01,
2.21188516478406399512e-01, 2.21384192048935862784e-01,
2.21579829338027028962e-01, 2.21775428360655529891e-01,
2.21970989131788226656e-01, 2.22166511666383154067e-01,
2.22361995979389603928e-01, 2.22557442085748097282e-01,
2.22752850000390412166e-01, 2.22948219738239528098e-01,
2.23143551314209764858e-01, 2.23338844743206588195e-01,
2.23534100040126831876e-01, 2.23729317219858586663e-01,
2.23924496297281144797e-01, 2.24119637287265222048e-01,
2.24314740204672707913e-01, 2.24509805064356859905e-01,
2.24704831881162248042e-01, 2.24899820669924727090e-01,
2.25094771445471492077e-01, 2.25289684222621078291e-01,
2.25484559016183333524e-01, 2.25679395840959445829e-01,
2.25874194711741999031e-01, 2.26068955643314889459e-01,
2.26263678650453381458e-01, 2.26458363747924135145e-01,
2.26653010950485178654e-01, 2.26847620272885880377e-01,
2.27042191729867087746e-01, 2.27236725336160932942e-01,
2.27431221106491082695e-01, 2.27625679055572488485e-01,
2.27820099198111608585e-01, 2.28014481548806269284e-01,
2.28208826122345775911e-01, 2.28403132933410801808e-01,
2.28597401996673554869e-01, 2.28791633326797638759e-01,
2.28985826938438108424e-01, 2.29179982846241497851e-01,
2.29374101064845820064e-01, 2.29568181608880567124e-01,
2.29762224492966654621e-01, 2.29956229731716588205e-01,
2.30150197339734297053e-01, 2.30344127331615244891e-01,
2.30538019721946374485e-01, 2.30731874525306190904e-01,
2.30925691756264706012e-01, 2.31119471429383438466e-01,
2.31313213559215469228e-01, 2.31506918160305386056e-01,
2.31700585247189394522e-01, 2.31894214834395206992e-01,
2.32087806936442098138e-01, 2.32281361567840904936e-01,
2.32474878743094054423e-01, 2.32668358476695591452e-01,
2.32861800783131095427e-01, 2.33055205676877763565e-01,
2.33248573172404383147e-01, 2.33441903284171359267e-01,
2.33635196026630714838e-01, 2.33828451414226118343e-01,
2.34021669461392772815e-01, 2.34214850182557637881e-01,
2.34407993592139235473e-01, 2.34601099704547760849e-01,
2.34794168534185027086e-01, 2.34987200095444576098e-01,
2.35180194402711567614e-01, 2.35373151470362834692e-01,
2.35566071312766911472e-01, 2.35758953944283977666e-01,
2.35951799379265969581e-01, 2.36144607632056469093e-01,
2.36337378716990786920e-01, 2.36530112648395907105e-01,
2.36722809440590598040e-01, 2.36915469107885301447e-01,
2.37108091664582215641e-01, 2.37300677124975240018e-01,
2.37493225503350030570e-01, 2.37685736813984055393e-01,
2.37878211071146455913e-01, 2.38070648289098130146e-01,
2.38263048482091843727e-01, 2.38455411664372063374e-01,
2.38647737850175012397e-01, 2.38840027053728753970e-01,
2.39032279289253135612e-01, 2.39224494570959789197e-01,
2.39416672913052186455e-01, 2.39608814329725555714e-01,
2.39800918835166965160e-01, 2.39992986443555350595e-01,
2.40185017169061459930e-01, 2.40377011025847825421e-01,
2.40568968028068902454e-01, 2.40760888189870903009e-01,
2.40952771525392017704e-01, 2.41144618048762221507e-01,
2.41336427774103329247e-01, 2.41528200715529106635e-01,
2.41719936887145159243e-01, 2.41911636303049015773e-01,
2.42103298977330017028e-01, 2.42294924924069510208e-01,
2.42486514157340682374e-01, 2.42678066691208643713e-01,
2.42869582539730455295e-01, 2.43061061716955018053e-01,
2.43252504236923267067e-01, 2.43443910113668032791e-01,
2.43635279361214096561e-01, 2.43826611993578135085e-01,
2.44017908024768859221e-01, 2.44209167468786902955e-01,
2.44400390339624878910e-01, 2.44591576651267350595e-01,
2.44782726417690915666e-01, 2.44973839652864094907e-01,
2.45164916370747443253e-01, 2.45355956585293522032e-01,
2.45546960310446843456e-01, 2.45737927560143981642e-01,
2.45928858348313489346e-01, 2.46119752688876008984e-01,
2.46310610595744133855e-01, 2.46501432082822546921e-01,
2.46692217164007937535e-01, 2.46882965853189056959e-01,
2.47073678164246746114e-01, 2.47264354111053824559e-01,
2.47454993707475257025e-01, 2.47645596967368042396e-01,
2.47836163904581269213e-01, 2.48026694532956060169e-01,
2.48217188866325710883e-01, 2.48407646918515578882e-01,
2.48598068703343083596e-01, 2.48788454234617817384e-01,
2.48978803526141462266e-01, 2.49169116591707789921e-01,
2.49359393445102717202e-01, 2.49549634100104333889e-01,
2.49739838570482819424e-01, 2.49930006870000470665e-01,
2.50120139012411812907e-01, 2.50310235011463488863e-01,
2.50500294880894314176e-01, 2.50690318634435249656e-01,
2.50880306285809429045e-01, 2.51070257848732159012e-01,
2.51260173336910974662e-01, 2.51450052764045639542e-01,
2.51639896143827923591e-01, 2.51829703489942047234e-01,
2.52019474816064292799e-01, 2.52209210135863171054e-01,
2.52398909462999421205e-01, 2.52588572811126066409e-01,
2.52778200193888302749e-01, 2.52967791624923554750e-01,
2.53157347117861530883e-01, 2.53346866686324168061e-01,
2.53536350343925687145e-01, 2.53725798104272537437e-01,
2.53915209980963452185e-01, 2.54104585987589448592e-01,
2.54293926137733827808e-01, 2.54483230444972119422e-01,
2.54672498922872247995e-01, 2.54861731584994311017e-01,
2.55050928444890800950e-01, 2.55240089516106494205e-01,
2.55429214812178506655e-01, 2.55618304346636182611e-01,
2.55807358133001372380e-01, 2.55996376184787988173e-01,
2.56185358515502614729e-01, 2.56374305138643843183e-01,
2.56563216067702881684e-01, 2.56752091316163111312e-01,
2.56940930897500419139e-01, 2.57129734825182976188e-01,
2.57318503112671292943e-01, 2.57507235773418385882e-01,
2.57695932820869499924e-01, 2.57884594268462385980e-01,
2.58073220129627134423e-01, 2.58261810417786286109e-01,
2.58450365146354721357e-01, 2.58638884328739770968e-01,
2.58827367978341271737e-01, 2.59015816108551233388e-01,
2.59204228732754393683e-01, 2.59392605864327774334e-01,
2.59580947516640792028e-01, 2.59769253703055424953e-01,
2.59957524436926046274e-01, 2.60145759731599535147e-01,
2.60333959600415110192e-01, 2.60522124056704607042e-01,
2.60710253113792256308e-01, 2.60898346784994794589e-01,
2.61086405083621408973e-01, 2.61274428022973848051e-01,
2.61462415616346366409e-01, 2.61650367877025558094e-01,
2.61838284818290800704e-01, 2.62026166453413700275e-01,
2.62214012795658535371e-01, 2.62401823858282146062e-01,
2.62589599654533822903e-01, 2.62777340197655417953e-01,
2.62965045500881344775e-01, 2.63152715577438522931e-01,
2.63340350440546488997e-01, 2.63527950103417285543e-01,
2.63715514579255572158e-01, 2.63903043881258514425e-01,
2.64090538022615839431e-01, 2.64277997016510002304e-01,
2.64465420876115908655e-01, 2.64652809614601136623e-01,
2.64840163245125714830e-01, 2.65027481780842510961e-01,
2.65214765234896787671e-01, 2.65402013620426591167e-01,
2.65589226950562473650e-01, 2.65776405238427604338e-01,
2.65963548497137936000e-01, 2.66150656739801871886e-01,
2.66337729979520598800e-01, 2.66524768229387865048e-01,
2.66711771502490091468e-01, 2.66898739811906371422e-01,
2.67085673170708526314e-01, 2.67272571591960883541e-01,
2.67459435088720665075e-01, 2.67646263674037598879e-01,
2.67833057360954085446e-01, 2.68019816162505419843e-01,
2.68206540091719403129e-01, 2.68393229161616619916e-01,
2.68579883385210327340e-01, 2.68766502775506566092e-01,
2.68953087345503938366e-01, 2.69139637108193996440e-01,
2.69326152076560909610e-01, 2.69512632263581464187e-01,
2.69699077682225452079e-01, 2.69885488345455115677e-01,
2.70071864266225758477e-01, 2.70258205457485134460e-01,
2.70444511932174003199e-01, 2.70630783703225796799e-01,
2.70817020783566675401e-01, 2.71003223186115638210e-01,
2.71189390923784467979e-01, 2.71375524009477731013e-01,
2.71561622456092832678e-01, 2.71747686276519850868e-01,
2.71933715483641758048e-01, 2.72119710090334365749e-01,
2.72305670109466269047e-01, 2.72491595553898846571e-01,
2.72677486436486371524e-01, 2.72863342770075956167e-01,
2.73049164567507385293e-01, 2.73234951841613560308e-01,
2.73420704605219999639e-01, 2.73606422871145227305e-01,
2.73792106652200495365e-01, 2.73977755961190061473e-01,
2.74163370810910911324e-01, 2.74348951214152980693e-01,
2.74534497183699099931e-01, 2.74720008732324993961e-01,
2.74905485872799226765e-01, 2.75090928617883312413e-01,
2.75276336980331548521e-01, 2.75461710972891293814e-01,
2.75647050608302801589e-01, 2.75832355899299108692e-01,
2.76017626858606257567e-01, 2.76202863498943240739e-01,
2.76388065833022056328e-01, 2.76573233873547430495e-01,
2.76758367633217150505e-01, 2.76943467124722064732e-01,
2.77128532360745749585e-01, 2.77313563353964953606e-01,
2.77498560117049208884e-01, 2.77683522662661164127e-01,
2.77868451003456307102e-01, 2.78053345152083242198e-01,
2.78238205121183468371e-01, 2.78423030923391545688e-01,
2.78607822571334928785e-01, 2.78792580077634188918e-01,
2.78977303454902791913e-01, 2.79161992715747264704e-01,
2.79346647872767195331e-01, 2.79531268938555177428e-01,
2.79715855925696699202e-01, 2.79900408846770476501e-01,
2.80084927714348175254e-01, 2.80269412540994466987e-01,
2.80453863339267139843e-01, 2.80638280121716932047e-01,
2.80822662900887809467e-01, 2.81007011689316577030e-01,
2.81191326499533322814e-01, 2.81375607344061084980e-01,
2.81559854235416073820e-01, 2.81744067186107394196e-01,
2.81928246208637434123e-01, 2.82112391315501587208e-01,
2.82296502519188363678e-01, 2.82480579832179334865e-01,
2.82664623266949355251e-01, 2.82848632835966118382e-01,
2.83032608551690600951e-01, 2.83216550426576951782e-01,
2.83400458473072325294e-01, 2.83584332703617048033e-01,
2.83768173130644618674e-01, 2.83951979766581652509e-01,
2.84135752623847881448e-01, 2.84319491714856320552e-01,
2.84503197052012990476e-01, 2.84686868647717139513e-01,
2.84870506514361188088e-01, 2.85054110664330728753e-01,
2.85237681110004581697e-01, 2.85421217863754628219e-01,
2.85604720937946032766e-01, 2.85788190344937187426e-01,
2.85971626097079545392e-01, 2.86155028206717843009e-01,
2.86338396686190099771e-01, 2.86521731547827507303e-01,
2.86705032803954318332e-01, 2.86888300466888235274e-01,
2.87071534548940077158e-01, 2.87254735062413890656e-01,
2.87437902019607005588e-01, 2.87621035432809979415e-01,
2.87804135314306597238e-01, 2.87987201676373927306e-01,
2.88170234531282265511e-01, 2.88353233891295246405e-01,
2.88536199768669621157e-01, 2.88719132175655535111e-01,
2.88902031124496472270e-01, 2.89084896627429033256e-01,
2.89267728696683157352e-01, 2.89450527344482233527e-01,
2.89633292583042656343e-01, 2.89816024424574436580e-01,
2.89998722881280646124e-01, 2.90181387965357862058e-01,
2.90364019688995778079e-01, 2.90546618064377593083e-01,
2.90729183103679733602e-01, 2.90911714819072020344e-01,
2.91094213222717501655e-01, 2.91276678326772675565e-01,
2.91459110143387378766e-01, 2.91641508684704731102e-01,
2.91823873962861302100e-01, 2.92006205989986888927e-01,
2.92188504778204849455e-01, 2.92370770339631658175e-01,
2.92553002686377461306e-01, 2.92735201830545521684e-01,
2.92917367784232607342e-01, 2.93099500559528880483e-01,
2.93281600168517952998e-01, 2.93463666623276664414e-01,
2.93645699935875470477e-01, 2.93827700118377999061e-01,
2.94009667182841549771e-01, 2.94191601141316649848e-01,
2.94373502005847331731e-01, 2.94555369788470966519e-01,
2.94737204501218597041e-01, 2.94919006156114382744e-01,
2.95100774765176154801e-01, 2.95282510340415083050e-01,
2.95464212893835898033e-01, 2.95645882437436613444e-01,
2.95827518983208914705e-01, 2.96009122543137770389e-01,
2.96190693129201765288e-01, 2.96372230753372822853e-01,
2.96553735427616482756e-01, 2.96735207163891623328e-01,
2.96916645974150794629e-01, 2.97098051870339885383e-01,
2.97279424864398345019e-01, 2.97460764968259128160e-01,
2.97642072193848694628e-01, 2.97823346553087064947e-01,
2.98004588057887653818e-01, 2.98185796720157547668e-01,
2.98366972551797282609e-01, 2.98548115564700899949e-01,
2.98729225770756001701e-01, 2.98910303181843861609e-01,
2.99091347809839036564e-01, 2.99272359666609866213e-01,
2.99453338764018139884e-01, 2.99634285113919263122e-01,
2.99815198728162091157e-01, 2.99996079618589261973e-01,
3.00176927797036752210e-01, 3.00357743275334321265e-01,
3.00538526065305122703e-01, 3.00719276178766037333e-01,
3.00899993627527506668e-01, 3.01080678423393532928e-01,
3.01261330578161790061e-01, 3.01441950103623457213e-01,
3.01622537011563440768e-01, 3.01803091313760207814e-01,
3.01983613021985786151e-01, 3.02164102148005930815e-01,
3.02344558703580013059e-01, 3.02524982700460964846e-01,
3.02705374150395445376e-01, 3.02885733065123674557e-01,
3.03066059456379655046e-01, 3.03246353335890839187e-01,
3.03426614715378517584e-01, 3.03606843606557541548e-01,
3.03787040021136489631e-01, 3.03967203970817556602e-01,
3.04147335467296719980e-01, 3.04327434522263462480e-01,
3.04507501147401160591e-01, 3.04687535354386640485e-01,
3.04867537154890677620e-01, 3.05047506560577552648e-01,
3.05227443583105328972e-01, 3.05407348234125741726e-01,
3.05587220525284364303e-01, 3.05767060468220275293e-01,
3.05946868074566447060e-01, 3.06126643355949523695e-01,
3.06306386323989821019e-01, 3.06486096990301493115e-01,
3.06665775366492365794e-01, 3.06845421464164047620e-01,
3.07025035294911874395e-01, 3.07204616870324909161e-01,
3.07384166201985997713e-01, 3.07563683301471768594e-01,
3.07743168180352633101e-01, 3.07922620850192618747e-01,
3.08102041322549813351e-01, 3.08281429608975809931e-01,
3.08460785721016095273e-01, 3.08640109670209994430e-01,
3.08819401468090559693e-01, 3.08998661126184626102e-01,
3.09177888656012922475e-01, 3.09357084069089849354e-01,
3.09536247376923756569e-01, 3.09715378591016721188e-01,
3.09894477722864714053e-01, 3.10073544783957377735e-01,
3.10252579785778359600e-01, 3.10431582739805034254e-01,
3.10610553657508725589e-01, 3.10789492550354429223e-01,
3.10968399429801145573e-01, 3.11147274307301602292e-01,
3.11326117194302476321e-01, 3.11504928102244282861e-01,
3.11683707042561319867e-01, 3.11862454026681890085e-01,
3.12041169066028079015e-01, 3.12219852172015865932e-01,
3.12398503356055123881e-01, 3.12577122629549564170e-01,
3.12755710003896902904e-01, 3.12934265490488583428e-01,
3.13112789100710109391e-01, 3.13291280845940822708e-01,
3.13469740737553903553e-01, 3.13648168786916592410e-01,
3.13826565005389856999e-01, 3.14004929404328836373e-01,
3.14183261995082285800e-01, 3.14361562788993187390e-01,
3.14539831797398306001e-01, 3.14718069031628300269e-01,
3.14896274503007833623e-01, 3.15074448222855574286e-01,
3.15252590202484084259e-01, 3.15430700453199819311e-01,
3.15608778986303351033e-01, 3.15786825813089033765e-01,
3.15964840944845282156e-01, 3.16142824392854515647e-01,
3.16320776168393047456e-01, 3.16498696282731251106e-01,
3.16676584747133449405e-01, 3.16854441572857969955e-01,
3.17032266771157145158e-01, 3.17210060353277145673e-01,
3.17387822330458424513e-01, 3.17565552713935272955e-01,
3.17743251514935987068e-01, 3.17920918744682867718e-01,
3.18098554414392331591e-01, 3.18276158535274800165e-01,
3.18453731118534588695e-01, 3.18631272175370239275e-01,
3.18808781716974187770e-01, 3.18986259754532985866e-01,
3.19163706299227134533e-01, 3.19341121362231306069e-01,
3.19518504954714122057e-01, 3.19695857087838430921e-01,
3.19873177772760863835e-01, 3.20050467020632389836e-01,
3.20227724842597871735e-01, 3.20404951249796343671e-01,
3.20582146253360900090e-01, 3.20759309864418695746e-01,
3.20936442094090945698e-01, 3.21113542953492980825e-01,
3.21290612453734303333e-01, 3.21467650605918364715e-01,
3.21644657421142898812e-01, 3.21821632910499588753e-01,
3.21998577085074344506e-01, 3.22175489955947080833e-01,
3.22352371534191939340e-01, 3.22529221830877121935e-01,
3.22706040857064946348e-01, 3.22882828623812012658e-01,
3.23059585142168759209e-01, 3.23236310423180128737e-01,
3.23413004477884902244e-01, 3.23589667317316198591e-01,
3.23766298952501196950e-01, 3.23942899394461303331e-01,
3.24119468654211984049e-01, 3.24296006742762987773e-01,
3.24472513671118123479e-01, 3.24648989450275538005e-01,
3.24825434091227327471e-01, 3.25001847604959981375e-01,
3.25178230002454049519e-01, 3.25354581294684308546e-01,
3.25530901492619706428e-01, 3.25707190607223473489e-01,
3.25883448649452955870e-01, 3.26059675630259726553e-01,
3.26235871560589585361e-01, 3.26412036451382503444e-01,
3.26588170313572789816e-01, 3.26764273158088813798e-01,
3.26940344995853338084e-01, 3.27116385837783185675e-01,
3.27292395694789517435e-01, 3.27468374577777776580e-01,
3.27644322497647522141e-01, 3.27820239465292706527e-01,
3.27996125491601397961e-01, 3.28171980587455947020e-01,
3.28347804763733097655e-01, 3.28523598031303654121e-01,
3.28699360401032869561e-01, 3.28875091883780168445e-01,
3.29050792490399257595e-01, 3.29226462231738181696e-01,
3.29402101118639156763e-01, 3.29577709161938792182e-01,
3.29753286372467979692e-01, 3.29928832761051837874e-01,
3.30104348338509878680e-01, 3.30279833115655840903e-01,
3.30455287103297801199e-01, 3.30630710312238174087e-01,
3.30806102753273600925e-01, 3.30981464437195116446e-01,
3.31156795374788148756e-01, 3.31332095576832297290e-01,
3.31507365054101610369e-01, 3.31682603817364363152e-01,
3.31857811877383335197e-01, 3.32032989244915477389e-01,
3.32208135930712189499e-01, 3.32383251945519209158e-01,
3.32558337300076611864e-01, 3.32733392005118810975e-01,
3.32908416071374668732e-01, 3.33083409509567329732e-01,
3.33258372330414331941e-01, 3.33433304544627551191e-01,
3.33608206162913423221e-01, 3.33783077195972499585e-01,
3.33957917654499891746e-01, 3.34132727549185049032e-01,
3.34307506890711869652e-01, 3.34482255689758534167e-01,
3.34656973956997838560e-01, 3.34831661703096694627e-01,
3.35006318938716629585e-01, 3.35180945674513619537e-01,
3.35355541921137811912e-01, 3.35530107689234080581e-01,
3.35704642989441526257e-01, 3.35879147832393754047e-01,
3.36053622228718762432e-01, 3.36228066189038998779e-01,
3.36402479723971414849e-01, 3.36576862844127355778e-01,
3.36751215560112560077e-01, 3.36925537882527326161e-01,
3.37099829821966401333e-01, 3.37274091389018870757e-01,
3.37448322594268379504e-01, 3.37622523448293077042e-01,
3.37796693961665561723e-01, 3.37970834144952825273e-01,
3.38144944008716419326e-01, 3.38319023563512344399e-01,
3.38493072819891160918e-01, 3.38667091788397822683e-01,
3.38841080479571843398e-01, 3.39015038903947185656e-01,
3.39188967072052427465e-01, 3.39362864994410484698e-01,
3.39536732681538888645e-01, 3.39710570143949730504e-01,
3.39884377392149494845e-01, 3.40058154436639281659e-01,
3.40231901287914695331e-01, 3.40405617956465900154e-01,
3.40579304452777453793e-01, 3.40752960787328640357e-01,
3.40926586970593192838e-01, 3.41100183013039404134e-01,
3.41273748925130071541e-01, 3.41447284717322607772e-01,
3.41620790400068985448e-01, 3.41794265983815681587e-01,
3.41967711479003788622e-01, 3.42141126896068903385e-01,
3.42314512245441293636e-01, 3.42487867537545731533e-01,
3.42661192782801549139e-01, 3.42834487991622693936e-01,
3.43007753174417784336e-01, 3.43180988341589887636e-01,
3.43354193503536686549e-01, 3.43527368670650590232e-01,
3.43700513853318456725e-01, 3.43873629061921814998e-01,
3.44046714306836864949e-01, 3.44219769598434255364e-01,
3.44392794947079416978e-01, 3.44565790363132395946e-01,
3.44738755856947631795e-01, 3.44911691438874568050e-01,
3.45084597119256875075e-01, 3.45257472908433227232e-01,
3.45430318816736692256e-01, 3.45603134854495064321e-01,
3.45775921032030753022e-01, 3.45948677359660894393e-01,
3.46121403847697239886e-01, 3.46294100506446100862e-01,
3.46466767346208570633e-01, 3.46639404377280413438e-01,
3.46812011609952008939e-01, 3.46984589054508352213e-01,
3.47157136721229275800e-01, 3.47329654620389172148e-01,
3.47502142762257104636e-01, 3.47674601157096863080e-01,
3.47847029815167019251e-01, 3.48019428746720593804e-01,
3.48191797962005611389e-01, 3.48364137471264545542e-01,
3.48536447284734762775e-01, 3.48708727412648133992e-01,
3.48880977865231478585e-01, 3.49053198652706175853e-01,
3.49225389785288331534e-01, 3.49397551273188777810e-01,
3.49569683126613184321e-01, 3.49741785355761836129e-01,
3.49913857970829800248e-01, 3.50085900982006870130e-01,
3.50257914399477510159e-01, 3.50429898233421077691e-01,
3.50601852494011601014e-01, 3.50773777191417779342e-01,
3.50945672335803204867e-01, 3.51117537937326196218e-01,
3.51289374006139798468e-01, 3.51461180552391783127e-01,
3.51632957586224814683e-01, 3.51804705117776228551e-01,
3.51976423157178197609e-01, 3.52148111714557621177e-01,
3.52319770800036180525e-01, 3.52491400423730505409e-01,
3.52663000595751729982e-01, 3.52834571326206047903e-01,
3.53006112625194323762e-01, 3.53177624502812259610e-01,
3.53349106969150339452e-01, 3.53520560034293884755e-01,
3.53691983708322998936e-01, 3.53863378001312622878e-01,
3.54034742923332534925e-01, 3.54206078484447295374e-01,
3.54377384694716357494e-01, 3.54548661564193900997e-01,
3.54719909102929054079e-01, 3.54891127320965671377e-01,
3.55062316228342556013e-01, 3.55233475835093293060e-01,
3.55404606151246360568e-01, 3.55575707186825074047e-01,
3.55746778951847530958e-01, 3.55917821456326777252e-01,
3.56088834710270696338e-01, 3.56259818723682064601e-01,
3.56430773506558440378e-01, 3.56601699068892386002e-01,
3.56772595420671190247e-01, 3.56943462571877201395e-01,
3.57114300532487438655e-01, 3.57285109312473980747e-01,
3.57455888921803799363e-01, 3.57626639370438537124e-01,
3.57797360668335062694e-01, 3.57968052825444915666e-01,
3.58138715851714584115e-01, 3.58309349757085504606e-01,
3.58479954551494006676e-01, 3.58650530244871368346e-01,
3.58821076847143705102e-01, 3.58991594368232136425e-01,
3.59162082818052619260e-01, 3.59332542206516170058e-01,
3.59502972543528642735e-01, 3.59673373838990784179e-01,
3.59843746102798400788e-01, 3.60014089344842191931e-01,
3.60184403575007805465e-01, 3.60354688803175782219e-01,
3.60524945039221667020e-01, 3.60695172293016008691e-01,
3.60865370574424193517e-01, 3.61035539893306722803e-01,
3.61205680259518935316e-01, 3.61375791682911229330e-01,
3.61545874173328896095e-01, 3.61715927740612286367e-01,
3.61885952394596643877e-01, 3.62055948145112271863e-01,
3.62225915001984422048e-01, 3.62395852975033405663e-01,
3.62565762074074371402e-01, 3.62735642308917638488e-01,
3.62905493689368474630e-01, 3.63075316225227040512e-01,
3.63245109926288667346e-01, 3.63414874802343634830e-01,
3.63584610863177171147e-01, 3.63754318118569619500e-01,
3.63923996578296327087e-01, 3.64093646252127589591e-01,
3.64263267149828817715e-01, 3.64432859281160426157e-01,
3.64602422655877833613e-01, 3.64771957283731573796e-01,
3.64941463174467128905e-01, 3.65110940337825040647e-01,
3.65280388783541021258e-01, 3.65449808521345675949e-01,
3.65619199560964724949e-01, 3.65788561912118947994e-01,
3.65957895584524239840e-01, 3.66127200587891499239e-01,
3.66296476931926684451e-01, 3.66465724626330868752e-01,
3.66634943680800184929e-01, 3.66804134105025769763e-01,
3.66973295908693986078e-01, 3.67142429101486200693e-01,
3.67311533693078839935e-01, 3.67480609693143445149e-01,
3.67649657111346728211e-01, 3.67818675957350349481e-01,
3.67987666240811250873e-01, 3.68156627971381322784e-01,
3.68325561158707626142e-01, 3.68494465812432392404e-01,
3.68663341942192857026e-01, 3.68832189557621481502e-01,
3.69001008668345675812e-01, 3.69169799283988242511e-01,
3.69338561414166821617e-01, 3.69507295068494445722e-01,
3.69676000256579095904e-01, 3.69844676988023979280e-01,
3.70013325272427417989e-01, 3.70181945119382904696e-01,
3.70350536538478991577e-01, 3.70519099539299512358e-01,
3.70687634131423415784e-01, 3.70856140324424710109e-01,
3.71024618127872685136e-01, 3.71193067551331690179e-01,
3.71361488604361411614e-01, 3.71529881296516484301e-01,
3.71698245637346880166e-01, 3.71866581636397741661e-01,
3.72034889303209215239e-01, 3.72203168647316895434e-01,
3.72371419678251380780e-01, 3.72539642405538495851e-01,
3.72707836838699291260e-01, 3.72876002987249988152e-01,
3.73044140860701978202e-01, 3.73212250468561934635e-01,
3.73380331820331756720e-01, 3.73548384925508347720e-01,
3.73716409793584058985e-01, 3.73884406434046412393e-01,
3.74052374856377989332e-01, 3.74220315070056763762e-01,
3.74388227084555880175e-01, 3.74556110909343709103e-01,
3.74723966553883902630e-01, 3.74891794027635172348e-01,
3.75059593340051733446e-01, 3.75227364500582805107e-01,
3.75395107518673054603e-01, 3.75562822403762208712e-01,
3.75730509165285331274e-01, 3.75898167812672767685e-01,
3.76065798355350089377e-01, 3.76233400802738204849e-01,
3.76400975164253082106e-01, 3.76568521449306137239e-01,
3.76736039667304067891e-01, 3.76903529827648686723e-01,
3.77070991939737309995e-01, 3.77238426012962257960e-01,
3.77405832056711409983e-01, 3.77573210080367704933e-01,
3.77740560093309529766e-01, 3.77907882104910441967e-01,
3.78075176124539447109e-01, 3.78242442161560721292e-01,
3.78409680225333722170e-01, 3.78576890325213299970e-01,
3.78744072470549641984e-01, 3.78911226670688106033e-01,
3.79078352934969442511e-01, 3.79245451272729794390e-01,
3.79412521693300530679e-01, 3.79579564206008357452e-01,
3.79746578820175262337e-01, 3.79913565545118681044e-01,
3.80080524390151330838e-01, 3.80247455364581210535e-01,
3.80414358477711711526e-01, 3.80581233738841562264e-01,
3.80748081157264828267e-01, 3.80914900742270912115e-01,
3.81081692503144608963e-01, 3.81248456449166051030e-01,
3.81415192589610707596e-01, 3.81581900933749385008e-01,
3.81748581490848337694e-01, 3.81915234270169157149e-01,
3.82081859280968716419e-01, 3.82248456532499392146e-01,
3.82415026034008842526e-01, 3.82581567794740229349e-01,
3.82748081823931884937e-01, 3.82914568130817700720e-01,
3.83081026724626960700e-01, 3.83247457614584230434e-01,
3.83413860809909523564e-01, 3.83580236319818357327e-01,
3.83746584153521419491e-01, 3.83912904320224956933e-01,
3.84079196829130664614e-01, 3.84245461689435519048e-01,
3.84411698910332055856e-01, 3.84577908501008036701e-01,
3.84744090470646837865e-01, 3.84910244828427117181e-01,
3.85076371583523036080e-01, 3.85242470745104093055e-01,
3.85408542322335401220e-01, 3.85574586324377355240e-01,
3.85740602760385797865e-01, 3.85906591639512019931e-01,
3.86072552970902815872e-01, 3.86238486763700372695e-01,
3.86404393027042381004e-01, 3.86570271770061868466e-01,
3.86736123001887421857e-01, 3.86901946731643076038e-01,
3.87067742968448313956e-01, 3.87233511721418011131e-01,
3.87399252999662713215e-01, 3.87564966812288136389e-01,
3.87730653168395777985e-01, 3.87896312077082416891e-01,
3.88061943547440391100e-01, 3.88227547588557486691e-01,
3.88393124209516937828e-01, 3.88558673419397537785e-01,
3.88724195227273583431e-01, 3.88889689642214819720e-01,
3.89055156673286495206e-01, 3.89220596329549362036e-01,
3.89386008620059675955e-01, 3.89551393553869196307e-01,
3.89716751140025186029e-01, 3.89882081387570522679e-01,
3.90047384305543420879e-01, 3.90212659902977765380e-01,
3.90377908188902833508e-01, 3.90543129172343517208e-01,
3.90708322862320267532e-01, 3.90873489267848928108e-01,
3.91038628397941012693e-01, 3.91203740261603483130e-01,
3.91368824867838915882e-01, 3.91533882225645335495e-01,
3.91698912344016436649e-01, 3.91863915231941306594e-01,
3.92028890898404758225e-01, 3.92193839352386997010e-01,
3.92358760602863898548e-01, 3.92523654658806786522e-01,
3.92688521529182710257e-01, 3.92853361222954111653e-01,
3.93018173749079158252e-01, 3.93182959116511465680e-01,
3.93347717334200208672e-01, 3.93512448411090343114e-01,
3.93677152356122161958e-01, 3.93841829178231628283e-01,
3.94006478886350375301e-01, 3.94171101489405484308e-01,
3.94335696996319762242e-01, 3.94500265416011519637e-01,
3.94664806757394681647e-01, 3.94829321029378788044e-01,
3.94993808240868993220e-01, 3.95158268400766010675e-01,
3.95322701517966224039e-01, 3.95487107601361631559e-01,
3.95651486659839735083e-01, 3.95815838702283817607e-01,
3.95980163737572665728e-01, 3.96144461774580736169e-01,
3.96308732822178044763e-01, 3.96472976889230388498e-01,
3.96637193984599012442e-01, 3.96801384117140887309e-01,
3.96965547295708709452e-01, 3.97129683529150678822e-01,
3.97293792826310665500e-01, 3.97457875196028209697e-01,
3.97621930647138466242e-01, 3.97785959188472371117e-01,
3.97949960828856363904e-01, 3.98113935577112609820e-01,
3.98277883442058888708e-01, 3.98441804432508706046e-01,
3.98605698557271237448e-01, 3.98769565825151217631e-01,
3.98933406244949217978e-01, 3.99097219825461368981e-01,
3.99261006575479415748e-01, 3.99424766503791051075e-01,
3.99588499619179360334e-01, 3.99752205930423210045e-01,
3.99915885446297303396e-01, 4.00079538175571791658e-01,
4.00243164127012718279e-01, 4.00406763309381685811e-01,
4.00570335731436077964e-01, 4.00733881401929004085e-01,
4.00897400329609188141e-01, 4.01060892523221135253e-01,
4.01224357991505076182e-01, 4.01387796743196800797e-01,
4.01551208787028046654e-01, 4.01714594131726110415e-01,
4.01877952786014125408e-01, 4.02041284758610784067e-01,
4.02204590058230671001e-01, 4.02367868693584040951e-01,
4.02531120673376818786e-01, 4.02694346006310877062e-01,
4.02857544701083536420e-01, 4.03020716766388009678e-01,
4.03183862210913346313e-01, 4.03346981043344210427e-01,
4.03510073272361047270e-01, 4.03673138906640027734e-01,
4.03836177954853103866e-01, 4.03999190425668119886e-01,
4.04162176327748423610e-01, 4.04325135669753310541e-01,
4.04488068460337746313e-01, 4.04650974708152644244e-01,
4.04813854421844421250e-01, 4.04976707610055497444e-01,
4.05139534281423963069e-01, 4.05302334444583689521e-01,
4.05465108108164384859e-01, 4.05627855280791482784e-01,
4.05790575971086253659e-01, 4.05953270187665749003e-01,
4.06115937939142745972e-01, 4.06278579234125969410e-01,
4.06441194081219814294e-01, 4.06603782489024567770e-01,
4.06766344466136187119e-01, 4.06928880021146577306e-01,
4.07091389162643424449e-01, 4.07253871899210195817e-01,
4.07416328239426139834e-01, 4.07578758191866397098e-01,
4.07741161765101944869e-01, 4.07903538967699541562e-01,
4.08065889808221726742e-01, 4.08228214295226987662e-01,
4.08390512437269537216e-01, 4.08552784242899424960e-01,
4.08715029720662648138e-01, 4.08877248879100985146e-01,
4.09039441726751940021e-01, 4.09201608272149075507e-01,
4.09363748523821679992e-01, 4.09525862490294934037e-01,
4.09687950180089799357e-01, 4.09850011601723129839e-01,
4.10012046763707727060e-01, 4.10174055674552173745e-01,
4.10336038342760889286e-01, 4.10497994776834240760e-01,
4.10659924985268376396e-01, 4.10821828976555447621e-01,
4.10983706759183275992e-01, 4.11145558341635852795e-01,
4.11307383732392728426e-01, 4.11469182939929623011e-01,
4.11630955972717926805e-01, 4.11792702839225033262e-01,
4.11954423547914172499e-01, 4.12116118107244577828e-01,
4.12277786525671208206e-01, 4.12439428811645081296e-01,
4.12601044973613051425e-01, 4.12762635020017809584e-01,
4.12924198959298049960e-01, 4.13085736799888414428e-01,
4.13247248550219326013e-01, 4.13408734218717210940e-01,
4.13570193813804387606e-01, 4.13731627343899122096e-01,
4.13893034817415517157e-01, 4.14054416242763789757e-01,
4.14215771628349826994e-01, 4.14377100982575685695e-01,
4.14538404313839203841e-01, 4.14699681630534222609e-01,
4.14860932941050530864e-01, 4.15022158253773809644e-01,
4.15183357577085743184e-01, 4.15344530919363852384e-01,
4.15505678288981772361e-01, 4.15666799694309030411e-01,
4.15827895143710990489e-01, 4.15988964645549075261e-01,
4.16150008208180710589e-01, 4.16311025839959270023e-01,
4.16472017549233963774e-01, 4.16632983344350116273e-01,
4.16793923233648999638e-01, 4.16954837225467778161e-01,
4.17115725328139674843e-01, 4.17276587549993804860e-01,
4.17437423899355397605e-01, 4.17598234384545574649e-01,
4.17759019013881405247e-01, 4.17919777795676072873e-01,
4.18080510738238597668e-01, 4.18241217849874169499e-01,
4.18401899138883814899e-01, 4.18562554613564674622e-01,
4.18723184282209781593e-01, 4.18883788153108282959e-01,
4.19044366234545218042e-01, 4.19204918534801795893e-01,
4.19365445062155117739e-01, 4.19525945824878288004e-01,
4.19686420831240469820e-01, 4.19846870089506885027e-01,
4.20007293607938703150e-01, 4.20167691394793096915e-01,
4.20328063458323408774e-01, 4.20488409806778928868e-01,
4.20648730448404839510e-01, 4.20809025391442659281e-01,
4.20969294644129632399e-01, 4.21129538214699283838e-01,
4.21289756111381030745e-01, 4.21449948342400404488e-01,
4.21610114915978995143e-01, 4.21770255840334340469e-01,
4.21930371123680147960e-01, 4.22090460774226183815e-01,
4.22250524800178161922e-01, 4.22410563209737965895e-01,
4.22570576011103482550e-01, 4.22730563212468657408e-01,
4.22890524822023494700e-01, 4.23050460847954223897e-01,
4.23210371298442855625e-01, 4.23370256181667792283e-01,
4.23530115505803272935e-01, 4.23689949279019761885e-01,
4.23849757509483726636e-01, 4.24009540205357748910e-01,
4.24169297374800524647e-01, 4.24329029025966752986e-01,
4.24488735167007302795e-01, 4.24648415806069157163e-01,
4.24808070951295302375e-01, 4.24967700610824949958e-01,
4.25127304792793314636e-01, 4.25286883505331780864e-01,
4.25446436756567736293e-01, 4.25605964554624793816e-01,
4.25765466907622680548e-01, 4.25924943823677126797e-01,
4.26084395310900088116e-01, 4.26243821377399578765e-01,
4.26403222031279727222e-01, 4.26562597280640942721e-01,
4.26721947133579471156e-01, 4.26881271598188005711e-01,
4.27040570682555131743e-01, 4.27199844394765715361e-01,
4.27359092742900625872e-01, 4.27518315735037068848e-01,
4.27677513379248142034e-01, 4.27836685683603279440e-01,
4.27995832656168084807e-01, 4.28154954305004109560e-01,
4.28314050638169185881e-01, 4.28473121663717371188e-01,
4.28632167389698781612e-01, 4.28791187824159647501e-01,
4.28950182975142479957e-01, 4.29109152850685904301e-01,
4.29268097458824715584e-01, 4.29427016807589878589e-01,
4.29585910905008472316e-01, 4.29744779759103801009e-01,
4.29903623377895449664e-01, 4.30062441769398950964e-01,
4.30221234941626229364e-01, 4.30380002902585323543e-01,
4.30538745660280330885e-01, 4.30697463222711796060e-01,
4.30856155597876211427e-01, 4.31014822793766405606e-01,
4.31173464818371321439e-01, 4.31332081679676238029e-01,
4.31490673385662437678e-01, 4.31649239944307483441e-01,
4.31807781363585274637e-01, 4.31966297651465769292e-01,
4.32124788815915150675e-01, 4.32283254864895827296e-01,
4.32441695806366432908e-01, 4.32600111648281937526e-01,
4.32758502398593258853e-01, 4.32916868065247761876e-01,
4.33075208656188981315e-01, 4.33233524179356677131e-01,
4.33391814642686779013e-01, 4.33550080054111552919e-01,
4.33708320421559379021e-01, 4.33866535752955029270e-01,
4.34024726056219334325e-01, 4.34182891339269516617e-01,
4.34341031610018912801e-01, 4.34499146876377251303e-01,
4.34657237146250430282e-01, 4.34815302427540573138e-01,
4.34973342728146084024e-01, 4.35131358055961647846e-01,
4.35289348418878174751e-01, 4.35447313824782800129e-01,
4.35605254281559051144e-01, 4.35763169797086569179e-01,
4.35921060379241387395e-01, 4.36078926035895708679e-01,
4.36236766774918072187e-01, 4.36394582604173242313e-01,
4.36552373531522319716e-01, 4.36710139564822685809e-01,
4.36867880711927891735e-01, 4.37025596980687935922e-01,
4.37183288378948931019e-01, 4.37340954914553436961e-01,
4.37498596595340183413e-01, 4.37656213429144347327e-01,
4.37813805423797164362e-01, 4.37971372587126372977e-01,
4.38128914926955992382e-01, 4.38286432451106211516e-01,
4.38443925167393611098e-01, 4.38601393083631108105e-01,
4.38758836207627955783e-01, 4.38916254547189521595e-01,
4.39073648110117731314e-01, 4.39231016904210735952e-01,
4.39388360937262911765e-01, 4.39545680217065026785e-01,
4.39702974751404296327e-01, 4.39860244548064049930e-01,
4.40017489614824119926e-01, 4.40174709959460508379e-01,
4.40331905589745720153e-01, 4.40489076513448429839e-01,
4.40646222738333759317e-01, 4.40803344272163166728e-01,
4.40960441122694446481e-01, 4.41117513297681618223e-01,
4.41274560804875204401e-01, 4.41431583652022063724e-01,
4.41588581846865335656e-01, 4.41745555397144495924e-01,
4.41902504310595412029e-01, 4.42059428594950398761e-01,
4.42216328257937996149e-01, 4.42373203307283191510e-01,
4.42530053750707252913e-01, 4.42686879595927895714e-01,
4.42843680850659227044e-01, 4.43000457522611579275e-01,
4.43157209619491843089e-01, 4.43313937149003189919e-01,
4.43470640118845127464e-01, 4.43627318536713610708e-01,
4.43783972410300986411e-01, 4.43940601747295937596e-01,
4.44097206555383594573e-01, 4.44253786842245423916e-01,
4.44410342615559339485e-01, 4.44566873882999535894e-01,
4.44723380652236766064e-01, 4.44879862930938063670e-01,
4.45036320726766909672e-01, 4.45192754047383121296e-01,
4.45349162900443018565e-01, 4.45505547293599368786e-01,
4.45661907234501164510e-01, 4.45818242730793901085e-01,
4.45974553790119576657e-01, 4.46130840420116525635e-01,
4.46287102628419529715e-01, 4.46443340422659651345e-01,
4.46599553810464677817e-01, 4.46755742799458455128e-01,
4.46911907397261609631e-01, 4.47068047611490881899e-01,
4.47224163449759737343e-01, 4.47380254919677866621e-01,
4.47536322028851463184e-01, 4.47692364784883112261e-01,
4.47848383195372012899e-01, 4.48004377267913589389e-01,
4.48160347010099879839e-01, 4.48316292429519203111e-01,
4.48472213533756491888e-01, 4.48628110330393070626e-01,
4.48783982827006711069e-01, 4.48939831031171632247e-01,
4.49095654950458444965e-01, 4.49251454592434429358e-01,
4.49407229964663146315e-01, 4.49562981074704659523e-01,
4.49718707930115535465e-01, 4.49874410538448787911e-01,
4.50030088907253877917e-01, 4.50185743044076824848e-01,
4.50341372956460039845e-01, 4.50496978651942492355e-01,
4.50652560138059488093e-01, 4.50808117422343002101e-01,
4.50963650512321345687e-01, 4.51119159415519443979e-01,
4.51274644139458558367e-01, 4.51430104691656619575e-01,
4.51585541079627950101e-01, 4.51740953310883319727e-01,
4.51896341392930112058e-01, 4.52051705333272157983e-01,
4.52207045139409735679e-01, 4.52362360818839792653e-01,
4.52517652379055612677e-01, 4.52672919827546982319e-01,
4.52828163171800412989e-01, 4.52983382419298696853e-01,
4.53138577577521295403e-01, 4.53293748653944061910e-01,
4.53448895656039463464e-01, 4.53604018591276414440e-01,
4.53759117467120498546e-01, 4.53914192291033691262e-01,
4.54069243070474470869e-01, 4.54224269812897984977e-01,
4.54379272525755772971e-01, 4.54534251216496043568e-01,
4.54689205892563397260e-01, 4.54844136561399159380e-01,
4.54999043230440991525e-01, 4.55153925907123280137e-01,
4.55308784598876803429e-01, 4.55463619313129008948e-01,
4.55618430057303847036e-01, 4.55773216838821770835e-01,
4.55927979665099847306e-01, 4.56082718543551757229e-01,
4.56237433481587573159e-01, 4.56392124486614148005e-01,
4.56546791566034670939e-01, 4.56701434727249055978e-01,
4.56856053977653775444e-01, 4.57010649324641693436e-01,
4.57165220775602509917e-01, 4.57319768337922372137e-01,
4.57474292018983930141e-01, 4.57628791826166447798e-01,
4.57783267766845969327e-01, 4.57937719848394764188e-01,
4.58092148078182048732e-01, 4.58246552463573320058e-01,
4.58400933011930911132e-01, 4.58555289730613546695e-01,
4.58709622626976676329e-01, 4.58863931708372252416e-01,
4.59018216982148952177e-01, 4.59172478455651955631e-01,
4.59326716136223001108e-01, 4.59480930031200551777e-01,
4.59635120147919573608e-01, 4.59789286493711701898e-01,
4.59943429075905130254e-01, 4.60097547901824721617e-01,
4.60251642978791952743e-01, 4.60405714314124858699e-01,
4.60559761915138143884e-01, 4.60713785789143015492e-01,
4.60867785943447572095e-01, 4.61021762385356193015e-01,
4.61175715122170148952e-01, 4.61329644161187268914e-01,
4.61483549509701884705e-01, 4.61637431175005163997e-01,
4.61791289164384777255e-01, 4.61945123485125008767e-01,
4.62098934144506923172e-01, 4.62252721149808087908e-01,
4.62406484508302795255e-01, 4.62560224227261951313e-01,
4.62713940313953076000e-01, 4.62867632775640358567e-01,
4.63021301619584713105e-01, 4.63174946853043612016e-01,
4.63328568483271197032e-01, 4.63482166517518334725e-01,
4.63635740963032505491e-01, 4.63789291827057803541e-01,
4.63942819116835103443e-01, 4.64096322839601782562e-01,
4.64249803002592054124e-01, 4.64403259613036689668e-01,
4.64556692678163130061e-01, 4.64710102205195596525e-01,
4.64863488201354924101e-01, 4.65016850673858561649e-01,
4.65170189629920738383e-01, 4.65323505076752297338e-01,
4.65476797021560750878e-01, 4.65630065471550447231e-01,
4.65783310433922237426e-01, 4.65936531915873697329e-01,
4.66089729924599238675e-01, 4.66242904467289775994e-01,
4.66396055551133059680e-01, 4.66549183183313398438e-01,
4.66702287371011992345e-01, 4.66855368121406655302e-01,
4.67008425441671759515e-01, 4.67161459338978624078e-01,
4.67314469820495126395e-01, 4.67467456893385868710e-01,
4.67620420564812233621e-01, 4.67773360841932217546e-01,
4.67926277731900652768e-01, 4.68079171241869040898e-01,
4.68232041378985497371e-01, 4.68384888150395028994e-01,
4.68537711563239256396e-01, 4.68690511624656580558e-01,
4.68843288341782127304e-01, 4.68996041721747636277e-01,
4.69148771771681794007e-01, 4.69301478498709900844e-01,
4.69454161909953870957e-01, 4.69606822012532620914e-01,
4.69759458813561625590e-01, 4.69912072320153140215e-01,
4.70064662539416200371e-01, 4.70217229478456510972e-01,
4.70369773144376612795e-01, 4.70522293544275715949e-01,
4.70674790685249866407e-01, 4.70827264574391779473e-01,
4.70979715218791006315e-01, 4.71132142625533822944e-01,
4.71284546801703230212e-01, 4.71436927754379064837e-01,
4.71589285490637777354e-01, 4.71741620017552876210e-01,
4.71893931342194261624e-01, 4.72046219471628891728e-01,
4.72198484412920449493e-01, 4.72350726173129231711e-01,
4.72502944759312482059e-01, 4.72655140178524169059e-01,
4.72807312437814986072e-01, 4.72959461544232517838e-01,
4.73111587504821018424e-01, 4.73263690326621577764e-01,
4.73415770016672121656e-01, 4.73567826582007300740e-01,
4.73719860029658546008e-01, 4.73871870366654179829e-01,
4.74023857600019193903e-01, 4.74175821736775415793e-01,
4.74327762783941508928e-01, 4.74479680748532972601e-01,
4.74631575637562030945e-01, 4.74783447458037688449e-01,
4.74935296216965896487e-01, 4.75087121921349220255e-01,
4.75238924578187227343e-01, 4.75390704194476154676e-01,
4.75542460777209186062e-01, 4.75694194333376174644e-01,
4.75845904869963920447e-01, 4.75997592393955948342e-01,
4.76149256912332674574e-01, 4.76300898432071240229e-01,
4.76452516960145788794e-01, 4.76604112503527188593e-01,
4.76755685069183032798e-01, 4.76907234664077916975e-01,
4.77058761295173217043e-01, 4.77210264969427089277e-01,
4.77361745693794636836e-01, 4.77513203475227632211e-01,
4.77664638320674905803e-01, 4.77816050237081957341e-01,
4.77967439231391233445e-01, 4.78118805310541961084e-01,
4.78270148481470258606e-01, 4.78421468751109080220e-01,
4.78572766126388271513e-01, 4.78724040614234402913e-01,
4.78875292221571102758e-01, 4.79026520955318668715e-01,
4.79177726822394400852e-01, 4.79328909829712324076e-01,
4.79480069984183521203e-01, 4.79631207292715744384e-01,
4.79782321762213748162e-01, 4.79933413399579067438e-01,
4.80084482211710183996e-01, 4.80235528205502359977e-01,
4.80386551387847859917e-01, 4.80537551765635728707e-01,
4.80688529345751902611e-01, 4.80839484135079264782e-01,
4.80990416140497478725e-01, 4.81141325368883154834e-01,
4.81292211827109794875e-01, 4.81443075522047847503e-01,
4.81593916460564486215e-01, 4.81744734649523886905e-01,
4.81895530095787172353e-01, 4.82046302806212301206e-01,
4.82197052787654012462e-01, 4.82347780046964158540e-01,
4.82498484590991372212e-01, 4.82649166426581233136e-01,
4.82799825560576212347e-01, 4.82950461999815616743e-01,
4.83101075751135811132e-01, 4.83251666821369940674e-01,
4.83402235217348152929e-01, 4.83552780945897431319e-01,
4.83703304013841761666e-01, 4.83853804428001965654e-01,
4.84004282195195867367e-01, 4.84154737322238126751e-01,
4.84305169815940406153e-01, 4.84455579683111259293e-01,
4.84605966930556131267e-01, 4.84756331565077469570e-01,
4.84906673593474557560e-01, 4.85056993022543792016e-01,
4.85207289859078350069e-01, 4.85357564109868300228e-01,
4.85507815781700824420e-01, 4.85658044881359884926e-01,
4.85808251415626557446e-01, 4.85958435391278642523e-01,
4.86108596815091109633e-01, 4.86258735693835708602e-01,
4.86408852034281247168e-01, 4.86558945843193424441e-01,
4.86709017127334886421e-01, 4.86859065893465337016e-01,
4.87009092148341260486e-01, 4.87159095898716310025e-01,
4.87309077151340919176e-01, 4.87459035912962579395e-01,
4.87608972190325673512e-01, 4.87758885990171697777e-01,
4.87908777319238984305e-01, 4.88058646184262812096e-01,
4.88208492591975629082e-01, 4.88358316549106552529e-01,
4.88508118062381979652e-01, 4.88657897138525088021e-01,
4.88807653784256113116e-01, 4.88957388006292237304e-01,
4.89107099811347700857e-01, 4.89256789206133579917e-01,
4.89406456197358119553e-01, 4.89556100791726400701e-01,
4.89705722995940617714e-01, 4.89855322816699856325e-01,
4.90004900260700204662e-01, 4.90154455334634808761e-01,
4.90303988045193817058e-01, 4.90453498399064324875e-01,
4.90602986402930429932e-01, 4.90752452063473232347e-01,
4.90901895387370890145e-01, 4.91051316381298508240e-01,
4.91200715051928193944e-01, 4.91350091405929167987e-01,
4.91499445449967542476e-01, 4.91648777190706487428e-01,
4.91798086634806175255e-01, 4.91947373788923836280e-01,
4.92096638659713703223e-01, 4.92245881253827011204e-01,
4.92395101577911997737e-01, 4.92544299638613958248e-01,
4.92693475442575246070e-01, 4.92842628996435161426e-01,
4.92991760306830117955e-01, 4.93140869380393531696e-01,
4.93289956223755765574e-01, 4.93439020843544351447e-01,
4.93588063246383768057e-01, 4.93737083438895607568e-01,
4.93886081427698409030e-01, 4.94035057219407824913e-01,
4.94184010820636510086e-01, 4.94332942237994232837e-01,
4.94481851478087708340e-01, 4.94630738547520820703e-01,
4.94779603452894345406e-01, 4.94928446200806226862e-01,
4.95077266797851522906e-01, 4.95226065250622127234e-01,
4.95374841565707269009e-01, 4.95523595749692957746e-01,
4.95672327809162538426e-01, 4.95821037750696136381e-01,
4.95969725580871212411e-01, 4.96118391306262063178e-01,
4.96267034933440265299e-01, 4.96415656468974286764e-01,
4.96564255919429764496e-01, 4.96712833291369393329e-01,
4.96861388591352926003e-01, 4.97009921825937173168e-01,
4.97158433001676058893e-01, 4.97306922125120620670e-01,
4.97455389202818953898e-01, 4.97603834241316156373e-01,
4.97752257247154494824e-01, 4.97900658226873293888e-01,
4.98049037187008991623e-01, 4.98197394134095139506e-01,
4.98345729074662346925e-01, 4.98494042015238225662e-01,
4.98642332962347667458e-01, 4.98790601922512566446e-01,
4.98938848902251819162e-01, 4.99087073908081657603e-01,
4.99235276946515205143e-01, 4.99383458024062754088e-01,
4.99531617147231821185e-01, 4.99679754322526759047e-01,
4.99827869556449311261e-01, 4.99975962855498223814e-01,
5.00124034226169245088e-01, 5.00272083674955569954e-01,
5.00420111208346951592e-01, 5.00568116832830867224e-01,
5.00716100554891574426e-01, 5.00864062381010444192e-01,
5.01012002317666071960e-01, 5.01159920371334166589e-01,
5.01307816548487550357e-01, 5.01455690855596269984e-01,
5.01603543299127152544e-01, 5.01751373885544693643e-01,
5.01899182621310058217e-01, 5.02046969512881746667e-01,
5.02194734566715483837e-01, 5.02342477789263885946e-01,
5.02490199186977015700e-01, 5.02637898766301716158e-01,
5.02785576533682276867e-01, 5.02933232495559989772e-01,
5.03080866658373260236e-01, 5.03228479028557940111e-01,
5.03376069612546661602e-01, 5.03523638416769281356e-01,
5.03671185447652880462e-01, 5.03818710711621875475e-01,
5.03966214215097574325e-01, 5.04113695964498398361e-01,
5.04261155966240215420e-01, 5.04408594226735784716e-01,
5.04556010752395311947e-01, 5.04703405549625783166e-01,
5.04850778624831741936e-01, 5.04998129984414623195e-01,
5.05145459634773197344e-01, 5.05292767582303348206e-01,
5.05440053833398073024e-01, 5.05587318394447704506e-01,
5.05734561271839577756e-01, 5.05881782471958252323e-01,
5.06028982001185512196e-01, 5.06176159865900365808e-01,
5.06323316072478935013e-01, 5.06470450627294455082e-01,
5.06617563536717607775e-01, 5.06764654807115966229e-01,
5.06911724444854328020e-01, 5.07058772456294937214e-01,
5.07205798847797040274e-01, 5.07352803625717108105e-01,
5.07499786796408614009e-01, 5.07646748366222699822e-01,
5.07793688341507287731e-01, 5.07940606728607746412e-01,
5.08087503533866335914e-01, 5.08234378763622984820e-01,
5.08381232424214291044e-01, 5.08528064521974632051e-01,
5.08674875063235165662e-01, 5.08821664054324496185e-01,
5.08968431501568119302e-01, 5.09115177411289310250e-01,
5.09261901789807902574e-01, 5.09408604643441509374e-01,
5.09555285978504746147e-01, 5.09701945801309230788e-01,
5.09848584118164027679e-01, 5.09995200935375647688e-01,
5.10141796259247382039e-01, 5.10288370096079968441e-01,
5.10434922452171369045e-01, 5.10581453333816770446e-01,
5.10727962747308583680e-01, 5.10874450698936555249e-01,
5.11020917194987545074e-01, 5.11167362241745526497e-01,
5.11313785845492030369e-01, 5.11460188012505589938e-01,
5.11606568749062073920e-01, 5.11752928061434575469e-01,
5.11899265955893412183e-01, 5.12045582438706237127e-01,
5.12191877516137816784e-01, 5.12338151194450253101e-01,
5.12484403479902872469e-01, 5.12630634378752336744e-01,
5.12776843897252421201e-01, 5.12923032041654236579e-01,
5.13069198818206229085e-01, 5.13215344233153958342e-01,
5.13361468292740430464e-01, 5.13507571003205542937e-01,
5.13653652370786972803e-01, 5.13799712401719177457e-01,
5.13945751102234282826e-01, 5.14091768478561528255e-01,
5.14237764536927266512e-01, 5.14383739283555296851e-01,
5.14529692724666865011e-01, 5.14675624866479997088e-01,
5.14821535715210387707e-01, 5.14967425277071066958e-01,
5.15113293558271956307e-01, 5.15259140565020756775e-01,
5.15404966303521949733e-01, 5.15550770779977685088e-01,
5.15696554000587226163e-01, 5.15842315971547171749e-01,
5.15988056699051345078e-01, 5.16133776189290904846e-01,
5.16279474448454456237e-01, 5.16425151482727717855e-01,
5.16570807298293632748e-01, 5.16716441901332701470e-01,
5.16862055298022426975e-01, 5.17007647494537869726e-01,
5.17153218497051314628e-01, 5.17298768311732271030e-01,
5.17444296944747583744e-01, 5.17589804402261544070e-01,
5.17735290690435445704e-01, 5.17880755815428361899e-01,
5.18026199783396146259e-01, 5.18171622600492431943e-01,
5.18317024272867854506e-01, 5.18462404806670384971e-01,
5.18607764208045662890e-01, 5.18753102483136108170e-01,
5.18898419638082031291e-01, 5.19043715679020523091e-01,
5.19188990612086342935e-01, 5.19334244443411474634e-01,
5.19479477179125348485e-01, 5.19624688825354508204e-01,
5.19769879388223055017e-01, 5.19915048873852092548e-01,
5.20060197288360503975e-01, 5.20205324637864174875e-01,
5.20350430928476548331e-01, 5.20495516166308069828e-01,
5.20640580357466964401e-01, 5.20785623508058459485e-01,
5.20930645624185340026e-01, 5.21075646711947504386e-01,
5.21220626777442519462e-01, 5.21365585826764954547e-01,
5.21510523866007047467e-01, 5.21655440901258149466e-01,
5.21800336938605058279e-01, 5.21945211984131907101e-01,
5.22090066043920164596e-01, 5.22234899124048745911e-01,
5.22379711230593901661e-01, 5.22524502369629217924e-01,
5.22669272547225505221e-01, 5.22814021769451131583e-01,
5.22958750042371911526e-01, 5.23103457372050661967e-01,
5.23248143764547868351e-01, 5.23392809225921240568e-01,
5.23537453762226157039e-01, 5.23682077379514887561e-01,
5.23826680083837370461e-01, 5.23971261881240990554e-01,
5.24115822777770357099e-01, 5.24260362779467303795e-01,
5.24404881892371554919e-01, 5.24549380122519615099e-01,
5.24693857475945879543e-01, 5.24838313958681745852e-01,
5.24982749576756169141e-01, 5.25127164336195551009e-01,
5.25271558243023517498e-01, 5.25415931303261363183e-01,
5.25560283522927385036e-01, 5.25704614908037548560e-01,
5.25848925464605154723e-01, 5.25993215198640950980e-01,
5.26137484116153020253e-01, 5.26281732223146669902e-01,
5.26425959525624986846e-01, 5.26570166029588282441e-01,
5.26714351741034092491e-01, 5.26858516665957621328e-01,
5.27002660810351297727e-01, 5.27146784180205107972e-01,
5.27290886781506484837e-01, 5.27434968620239974513e-01,
5.27579029702387902745e-01, 5.27723070033929708700e-01,
5.27867089620842389053e-01, 5.28011088469100386966e-01,
5.28155066584675592090e-01, 5.28299023973537229537e-01,
5.28442960641651859888e-01, 5.28586876594983601230e-01,
5.28730771839494129161e-01, 5.28874646381142232698e-01,
5.29018500225884258370e-01, 5.29162333379674110212e-01,
5.29306145848463027725e-01, 5.29449937638199585876e-01,
5.29593708754829917140e-01, 5.29737459204297600479e-01,
5.29881188992543661342e-01, 5.30024898125506349622e-01,
5.30168586609121583741e-01, 5.30312254449322728611e-01,
5.30455901652040484606e-01, 5.30599528223202998589e-01,
5.30743134168735974932e-01, 5.30886719494562342447e-01,
5.31030284206602809505e-01, 5.31173828310775197892e-01,
5.31317351812994997928e-01, 5.31460854719175146421e-01,
5.31604337035225804620e-01, 5.31747798767055024349e-01,
5.31891239920567859834e-01, 5.32034660501667033827e-01,
5.32178060516252715573e-01, 5.32321439970222631821e-01,
5.32464798869471844789e-01, 5.32608137219892863179e-01,
5.32751455027375753204e-01, 5.32894752297807916541e-01,
5.33038029037074423400e-01, 5.33181285251057679453e-01,
5.33324520945637647884e-01, 5.33467736126691627341e-01,
5.33610930800094473980e-01, 5.33754104971718490447e-01,
5.33897258647433536893e-01, 5.34040391833106919961e-01,
5.34183504534603503799e-01, 5.34326596757785265979e-01,
5.34469668508512185667e-01, 5.34612719792641466476e-01,
5.34755750616027647482e-01, 5.34898760984523158335e-01,
5.35041750903977431086e-01, 5.35184720380237788362e-01,
5.35327669419148999275e-01, 5.35470598026553057380e-01,
5.35613506208289624766e-01, 5.35756393970195921028e-01,
5.35899261318106612251e-01, 5.36042108257853922026e-01,
5.36184934795267298391e-01, 5.36327740936173968933e-01,
5.36470526686398718752e-01, 5.36613292051763668411e-01,
5.36756037038088384961e-01, 5.36898761651190215005e-01,
5.37041465896883618569e-01, 5.37184149780981057276e-01,
5.37326813309292106169e-01, 5.37469456487623897800e-01,
5.37612079321781455299e-01, 5.37754681817566693169e-01,
5.37897263980779749559e-01, 5.38039825817217653992e-01,
5.38182367332675215543e-01, 5.38324888532945022845e-01,
5.38467389423816666927e-01, 5.38609870011077740415e-01,
5.38752330300513060379e-01, 5.38894770297905112422e-01,
5.39037190009033828630e-01, 5.39179589439676698603e-01,
5.39321968595608880470e-01, 5.39464327482602756803e-01,
5.39606666106428600749e-01, 5.39748984472854020922e-01,
5.39891282587644072422e-01, 5.40033560456561589902e-01,
5.40175818085366854504e-01, 5.40318055479817593856e-01,
5.40460272645669204117e-01, 5.40602469588674527934e-01,
5.40744646314584076485e-01, 5.40886802829145696414e-01,
5.41028939138105124940e-01, 5.41171055247205212702e-01,
5.41313151162186700915e-01, 5.41455226888787888306e-01,
5.41597282432744409064e-01, 5.41739317799789454888e-01,
5.41881332995654108053e-01, 5.42023328026066675278e-01,
5.42165302896753020789e-01, 5.42307257613436899391e-01,
5.42449192181839179305e-01, 5.42591106607678730356e-01,
5.42733000896671757829e-01, 5.42874875054531913499e-01,
5.43016729086970628693e-01, 5.43158562999696892248e-01,
5.43300376798417139490e-01, 5.43442170488835474274e-01,
5.43583944076653557964e-01, 5.43725697567570720459e-01,
5.43867430967283516097e-01, 5.44009144281486500816e-01,
5.44150837515871677041e-01, 5.44292510676128493685e-01,
5.44434163767944068191e-01, 5.44575796797003186533e-01,
5.44717409768987970153e-01, 5.44859002689578542089e-01,
5.45000575564452249822e-01, 5.45142128399284109364e-01,
5.45283661199746805259e-01, 5.45425173971510579563e-01,
5.45566666720243342859e-01, 5.45708139451610341197e-01,
5.45849592171274711205e-01, 5.45991024884897147018e-01,
5.46132437598135678236e-01, 5.46273830316646225036e-01,
5.46415203046082265104e-01, 5.46556555792094611590e-01,
5.46697888560332190266e-01, 5.46839201356441040325e-01,
5.46980494186064980511e-01, 5.47121767054845498102e-01,
5.47263019968421748906e-01, 5.47404252932430224199e-01,
5.47545465952505305829e-01, 5.47686659034278933156e-01,
5.47827832183380492026e-01, 5.47968985405437147840e-01,
5.48110118706073623507e-01, 5.48251232090912310468e-01,
5.48392325565573157675e-01, 5.48533399135673782610e-01,
5.48674452806829471285e-01, 5.48815486584652956203e-01,
5.48956500474754749419e-01, 5.49097494482743031519e-01,
5.49238468614223429576e-01, 5.49379422874799350218e-01,
5.49520357270071757583e-01, 5.49661271805639173316e-01,
5.49802166487098009640e-01, 5.49943041320042236286e-01,
5.50083896310063047430e-01, 5.50224731462749860889e-01,
5.50365546783689540966e-01, 5.50506342278466287432e-01,
5.50647117952662301654e-01, 5.50787873811857342510e-01,
5.50928609861628726385e-01, 5.51069326107551438199e-01,
5.51210022555198242422e-01, 5.51350699210139350015e-01,
5.51491356077942862512e-01, 5.51631993164174216915e-01,
5.51772610474396740798e-01, 5.51913208014171430271e-01,
5.52053785789056838951e-01, 5.52194343804609077964e-01,
5.52334882066382037991e-01, 5.52475400579927389266e-01,
5.52615899350794248512e-01, 5.52756378384529512005e-01,
5.52896837686677744550e-01, 5.53037277262781068465e-01,
5.53177697118379274599e-01, 5.53318097259010044375e-01,
5.53458477690208505706e-01, 5.53598838417507566056e-01,
5.53739179446437690402e-01, 5.53879500782527012248e-01,
5.54019802431301555679e-01, 5.54160084398284791263e-01,
5.54300346688997858102e-01, 5.54440589308959896897e-01,
5.54580812263687272790e-01, 5.54721015558694352521e-01,
5.54861199199493171363e-01, 5.55001363191593100055e-01,
5.55141507540501621953e-01, 5.55281632251723666904e-01,
5.55421737330761944307e-01, 5.55561822783116832092e-01,
5.55701888614286376722e-01, 5.55841934829766293191e-01,
5.55981961435050076048e-01, 5.56121968435628777350e-01,
5.56261955836991228708e-01, 5.56401923644624041287e-01,
5.56541871864011383764e-01, 5.56681800500635093343e-01,
5.56821709559974897807e-01, 5.56961599047508082450e-01,
5.57101468968709601093e-01, 5.57241319329052187115e-01,
5.57381150134006353447e-01, 5.57520961389040059508e-01,
5.57660753099619377338e-01, 5.57800525271207603417e-01,
5.57940277909266035827e-01, 5.58080011019253752202e-01,
5.58219724606627387686e-01, 5.58359418676841245954e-01,
5.58499093235347632280e-01, 5.58638748287596076381e-01,
5.58778383839034331615e-01, 5.58917999895107486807e-01,
5.59057596461258632381e-01, 5.59197173542928527290e-01,
5.59336731145555376976e-01, 5.59476269274575499502e-01,
5.59615787935422659416e-01, 5.59755287133528511845e-01,
5.59894766874322380446e-01, 5.60034227163231146385e-01,
5.60173668005679803450e-01, 5.60313089407090680893e-01,
5.60452491372884220588e-01, 5.60591873908478199873e-01,
5.60731237019288286660e-01, 5.60870580710728150464e-01,
5.61009904988208907284e-01, 5.61149209857139341651e-01,
5.61288495322926128672e-01, 5.61427761390973834033e-01,
5.61567008066684469902e-01, 5.61706235355457939029e-01,
5.61845443262691812691e-01, 5.61984631793781552744e-01,
5.62123800954120289575e-01, 5.62262950749098933123e-01,
5.62402081184105950840e-01, 5.62541192264527811773e-01,
5.62680283995748653503e-01, 5.62819356383150282142e-01,
5.62958409432112505399e-01, 5.63097443148012466452e-01,
5.63236457536225532117e-01, 5.63375452602124515700e-01,
5.63514428351080010060e-01, 5.63653384788460498633e-01,
5.63792321919632244409e-01, 5.63931239749959178909e-01,
5.64070138284803013207e-01, 5.64209017529523126910e-01,
5.64347877489476790203e-01, 5.64486718170019163843e-01,
5.64625539576502966099e-01, 5.64764341714278694795e-01,
5.64903124588694849351e-01, 5.65041888205097375675e-01,
5.65180632568830110252e-01, 5.65319357685234891164e-01,
5.65458063559651002983e-01, 5.65596750197415842898e-01,
5.65735417603864143565e-01, 5.65874065784328972306e-01,
5.66012694744140620884e-01, 5.66151304488627493683e-01,
5.66289895023115885664e-01, 5.66428466352929538274e-01,
5.66567018483390194561e-01, 5.66705551419817266101e-01,
5.66844065167528166072e-01, 5.66982559731837976180e-01,
5.67121035118059335645e-01, 5.67259491331503107325e-01,
5.67397928377477600570e-01, 5.67536346261289237347e-01,
5.67674744988241775090e-01, 5.67813124563637305897e-01,
5.67951484992775368355e-01, 5.68089826280953391624e-01,
5.68228148433466695444e-01, 5.68366451455608157062e-01,
5.68504735352668766346e-01, 5.68643000129937070675e-01,
5.68781245792699508002e-01, 5.68919472346240517879e-01,
5.69057679795841986348e-01, 5.69195868146784023089e-01,
5.69334037404344073252e-01, 5.69472187573797694604e-01,
5.69610318660418335490e-01, 5.69748430669477001764e-01,
5.69886523606242811901e-01, 5.70024597475982330863e-01,
5.70162652283960236232e-01, 5.70300688035438985146e-01,
5.70438704735678814295e-01, 5.70576702389937739923e-01,
5.70714681003471557830e-01, 5.70852640581534065412e-01,
5.70990581129376728597e-01, 5.71128502652249014915e-01,
5.71266405155397949400e-01, 5.71404288644068669711e-01,
5.71542153123503982037e-01, 5.71679998598944472121e-01,
5.71817825075628838327e-01, 5.71955632558793225506e-01,
5.72093421053671891130e-01, 5.72231190565496872225e-01,
5.72368941099498096392e-01, 5.72506672660903048744e-01,
5.72644385254937327012e-01, 5.72782078886824419506e-01,
5.72919753561785483065e-01, 5.73057409285039565106e-01,
5.73195046061803492599e-01, 5.73332663897292205135e-01,
5.73470262796718088794e-01, 5.73607842765291753295e-01,
5.73745403808221365871e-01, 5.73882945930713095350e-01,
5.74020469137971001139e-01, 5.74157973435197033218e-01,
5.74295458827590588058e-01, 5.74432925320349507814e-01,
5.74570372918669192153e-01, 5.74707801627742709272e-01,
5.74845211452761462034e-01, 5.74982602398914188768e-01,
5.75119974471387962467e-01, 5.75257327675367413633e-01,
5.75394662016035063345e-01, 5.75531977498571434282e-01,
5.75669274128154828674e-01, 5.75806551909961439328e-01,
5.75943810849165349630e-01, 5.76081050950938422517e-01,
5.76218272220450522525e-01, 5.76355474662869182723e-01,
5.76492658283360159821e-01, 5.76629823087086545996e-01,
5.76766969079209990134e-01, 5.76904096264889365564e-01,
5.77041204649281769257e-01, 5.77178294237542299783e-01,
5.77315365034823613222e-01, 5.77452417046276367252e-01,
5.77589450277049221150e-01, 5.77726464732288613746e-01,
5.77863460417138763425e-01, 5.78000437336742001193e-01,
5.78137395496238437609e-01, 5.78274334900766073808e-01,
5.78411255555460690481e-01, 5.78548157465456180937e-01,
5.78685040635884107019e-01, 5.78821905071874143189e-01,
5.78958750778553632443e-01, 5.79095577761048030396e-01,
5.79232386024480461195e-01, 5.79369175573972161608e-01,
5.79505946414642258979e-01, 5.79642698551607438162e-01,
5.79779431989982829698e-01, 5.79916146734881010616e-01,
5.80052842791412559542e-01, 5.80189520164686278747e-01,
5.80326178859808416988e-01, 5.80462818881883446664e-01,
5.80599440236013508709e-01, 5.80736042927298967697e-01,
5.80872626960837856736e-01, 5.81009192341726099507e-01,
5.81145739075057621292e-01, 5.81282267165924348973e-01,
5.81418776619415988982e-01, 5.81555267440620138331e-01,
5.81691739634622506649e-01, 5.81828193206506472102e-01,
5.81964628161353414448e-01, 5.82101044504242826072e-01,
5.82237442240251867887e-01, 5.82373821374455813427e-01,
5.82510181911927604759e-01, 5.82646523857738407592e-01,
5.82782847216957056169e-01, 5.82919151994650497350e-01,
5.83055438195883679597e-01, 5.83191705825719108880e-01,
5.83327954889217514811e-01, 5.83464185391437628603e-01,
5.83600397337435849998e-01, 5.83736590732266802384e-01,
5.83872765580982666656e-01, 5.84008921888633958375e-01,
5.84145059660268861634e-01, 5.84281178900933673148e-01,
5.84417279615672580206e-01, 5.84553361809527549653e-01,
5.84689425487538660953e-01, 5.84825470654743884147e-01,
5.84961497316179301897e-01, 5.85097505476878554376e-01,
5.85233495141873616419e-01, 5.85369466316194131394e-01,
5.85505419004867966315e-01, 5.85641353212920767746e-01,
5.85777268945375961806e-01, 5.85913166207255309281e-01,
5.86049045003578239488e-01, 5.86184905339362183341e-01,
5.86320747219622684376e-01, 5.86456570649373176707e-01,
5.86592375633624762976e-01, 5.86728162177386880494e-01,
5.86863930285666857145e-01, 5.86999679963469911392e-01,
5.87135411215799041251e-01, 5.87271124047655579403e-01,
5.87406818464038527061e-01, 5.87542494469945109081e-01,
5.87678152070370218851e-01, 5.87813791270306862380e-01,
5.87949412074746158297e-01, 5.88085014488676893762e-01,
5.88220598517086079582e-01, 5.88356164164958506113e-01,
5.88491711437277187358e-01, 5.88627240339022916871e-01,
5.88762750875174489806e-01, 5.88898243050708591895e-01,
5.89033716870600132509e-01, 5.89169172339821800577e-01,
5.89304609463344397646e-01, 5.89440028246136504819e-01,
5.89575428693164815819e-01, 5.89710810809394025966e-01,
5.89846174599786832182e-01, 5.89981520069303932985e-01,
5.90116847222903695425e-01, 5.90252156065543043262e-01,
5.90387446602176346744e-01, 5.90522718837756310784e-01,
5.90657972777233530870e-01, 5.90793208425556493069e-01,
5.90928425787671796066e-01, 5.91063624868523929123e-01,
5.91198805673055605148e-01, 5.91333968206207205576e-01,
5.91469112472917446510e-01, 5.91604238478122712586e-01,
5.91739346226757612079e-01, 5.91874435723754643845e-01,
5.92009506974044419358e-01, 5.92144559982555440669e-01,
5.92279594754214322450e-01, 5.92414611293945458925e-01,
5.92549609606671578987e-01, 5.92684589697313191081e-01,
5.92819551570788805250e-01, 5.92954495232015155182e-01,
5.93089420685906643094e-01, 5.93224327937376005870e-01,
5.93359216991333870972e-01, 5.93494087852688756435e-01,
5.93628940526347403939e-01, 5.93763775017214334717e-01,
5.93898591330192404669e-01, 5.94033389470182138226e-01,
5.94168169442082394482e-01, 5.94302931250789812090e-01,
5.94437674901199142319e-01, 5.94572400398203249061e-01,
5.94707107746692775763e-01, 5.94841796951556700535e-01,
5.94976468017681670020e-01, 5.95111120949952776549e-01,
5.95245755753252669962e-01, 5.95380372432462556809e-01,
5.95514970992461090127e-01, 5.95649551438125590686e-01,
5.95784113774330714719e-01, 5.95918658005949786194e-01,
5.96053184137853686586e-01, 5.96187692174911743059e-01,
5.96322182121990951309e-01, 5.96456653983956530674e-01,
5.96591107765671591068e-01, 5.96725543471997688094e-01,
5.96859961107793823842e-01, 5.96994360677917557112e-01,
5.97128742187224115234e-01, 5.97263105640566949184e-01,
5.97397451042797622556e-01, 5.97531778398765700544e-01,
5.97666087713318527896e-01, 5.97800378991301784026e-01,
5.97934652237559260968e-01, 5.98068907456932641331e-01,
5.98203144654261498303e-01, 5.98337363834383739736e-01,
5.98471565002135386102e-01, 5.98605748162350126407e-01,
5.98739913319859984320e-01, 5.98874060479495096132e-01,
5.99008189646083377689e-01, 5.99142300824451079500e-01,
5.99276394019422453674e-01, 5.99410469235819531875e-01,
5.99544526478462791452e-01, 5.99678565752170600334e-01,
5.99812587061759439067e-01, 5.99946590412043678775e-01,
6.00080575807836025248e-01, 6.00214543253947074852e-01,
6.00348492755185425551e-01, 6.00482424316358009975e-01,
6.00616337942269540306e-01, 6.00750233637722952373e-01,
6.00884111407519294623e-01, 6.01017971256457506080e-01,
6.01151813189334860432e-01, 6.01285637210946410924e-01,
6.01419443326085545465e-01, 6.01553231539543431516e-01,
6.01687001856109793252e-01, 6.01820754280571801331e-01,
6.01954488817715294147e-01, 6.02088205472323889644e-01,
6.02221904249179207369e-01, 6.02355585153061201531e-01,
6.02489248188747716917e-01, 6.02622893361014821956e-01,
6.02756520674636475654e-01, 6.02890130134384971683e-01,
6.03023721745030605312e-01, 6.03157295511341451366e-01,
6.03290851438084252401e-01, 6.03424389530023419503e-01,
6.03557909791921476383e-01, 6.03691412228539170393e-01,
6.03824896844635472526e-01, 6.03958363644967022310e-01,
6.04091812634289015982e-01, 6.04225243817354318310e-01,
6.04358657198914350772e-01, 6.04492052783718314402e-01,
6.04625430576513633874e-01, 6.04758790582045624440e-01,
6.04892132805058047040e-01, 6.05025457250292553191e-01,
6.05158763922488907028e-01, 6.05292052826384985309e-01,
6.05425323966716888435e-01, 6.05558577348218607384e-01,
6.05691812975622467796e-01, 6.05825030853658685892e-01,
6.05958230987055701533e-01, 6.06091413380540178224e-01,
6.06224578038836670046e-01, 6.06357724966668065747e-01,
6.06490854168755144649e-01, 6.06623965649816909718e-01,
6.06757059414570476541e-01, 6.06890135467731184349e-01,
6.07023193814012262948e-01, 6.07156234458125165787e-01,
6.07289257404779569960e-01, 6.07422262658683154157e-01,
6.07555250224541820714e-01, 6.07688220107059362540e-01,
6.07821172310938018235e-01, 6.07954106840877805951e-01,
6.08087023701577300550e-01, 6.08219922897732745426e-01,
6.08352804434038829662e-01, 6.08485668315188243938e-01,
6.08618514545871902577e-01, 6.08751343130778610480e-01,
6.08884154074595507211e-01, 6.09016947382007955980e-01,
6.09149723057699321593e-01, 6.09282481106350970457e-01,
6.09415221532642714664e-01, 6.09547944341252145861e-01,
6.09680649536855301385e-01, 6.09813337124126220168e-01,
6.09946007107737053765e-01, 6.10078659492358177374e-01,
6.10211294282658078814e-01, 6.10343911483303358523e-01,
6.10476511098958729562e-01, 6.10609093134287128635e-01,
6.10741657593949716087e-01, 6.10874204482605542843e-01,
6.11006733804912105512e-01, 6.11139245565524680259e-01,
6.11271739769097099959e-01, 6.11404216420281088062e-01,
6.11536675523726702686e-01, 6.11669117084081892521e-01,
6.11801541105992940928e-01, 6.11933947594104243883e-01,
6.12066336553058421011e-01, 6.12198707987496204552e-01,
6.12331061902056439372e-01, 6.12463398301376193977e-01,
6.12595717190090538473e-01, 6.12728018572832988653e-01,
6.12860302454234950886e-01, 6.12992568838926166208e-01,
6.13124817731534488274e-01, 6.13257049136685772339e-01,
6.13389263059004430367e-01, 6.13521459503112542855e-01,
6.13653638473630858030e-01, 6.13785799975177903676e-01,
6.13917944012370542239e-01, 6.14050070589823748790e-01,
6.14182179712150722040e-01, 6.14314271383962884343e-01,
6.14446345609869770676e-01, 6.14578402394478917614e-01,
6.14710441742396418441e-01, 6.14842463658226145995e-01,
6.14974468146570418803e-01, 6.15106455212029668012e-01,
6.15238424859202437389e-01, 6.15370377092685383325e-01,
6.15502311917073607894e-01, 6.15634229336960214773e-01,
6.15766129356936420258e-01, 6.15898011981591775310e-01,
6.16029877215514054534e-01, 6.16161725063288923110e-01,
6.16293555529500491907e-01, 6.16425368618731095438e-01,
6.16557164335561069812e-01, 6.16688942684569085806e-01,
6.16820703670331926816e-01, 6.16952447297424488859e-01,
6.17084173570420113641e-01, 6.17215882493890033444e-01,
6.17347574072403926237e-01, 6.17479248310529471588e-01,
6.17610905212832794753e-01, 6.17742544783877911563e-01,
6.17874167028227172516e-01, 6.18005771950441151752e-01,
6.18137359555078758078e-01, 6.18268929846696679853e-01,
6.18400482829850384192e-01, 6.18532018509092895719e-01,
6.18663536888976017813e-01, 6.18795037974049555451e-01,
6.18926521768861204187e-01, 6.19057988277957438328e-01,
6.19189437505882511736e-01, 6.19320869457179012940e-01,
6.19452284136387754110e-01, 6.19583681548047882082e-01,
6.19715061696696434268e-01, 6.19846424586868893769e-01,
6.19977770223098967328e-01, 6.20109098609918474310e-01,
6.20240409751857568743e-01, 6.20371703653444406257e-01,
6.20502980319205588167e-01, 6.20634239753665939432e-01,
6.20765481961348286610e-01, 6.20896706946773790925e-01,
6.21027914714461837242e-01, 6.21159105268930034072e-01,
6.21290278614694324588e-01, 6.21421434756268653565e-01,
6.21552573698165300442e-01, 6.21683695444894879323e-01,
6.21814800000966005911e-01, 6.21945887370885630574e-01,
6.22076957559158927324e-01, 6.22208010570289515861e-01,
6.22339046408778795438e-01, 6.22470065079126610996e-01,
6.22601066585831364186e-01, 6.22732050933389125191e-01,
6.22863018126294520904e-01, 6.22993968169040401861e-01,
6.23124901066117842241e-01, 6.23255816822016028844e-01,
6.23386715441222483136e-01, 6.23517596928222950226e-01,
6.23648461287501509887e-01, 6.23779308523540354514e-01,
6.23910138640819900147e-01, 6.24040951643819008510e-01,
6.24171747537014431906e-01, 6.24302526324881368325e-01,
6.24433288011893461444e-01, 6.24564032602522356541e-01,
6.24694760101237811512e-01, 6.24825470512508140963e-01,
6.24956163840799772125e-01, 6.25086840090577355866e-01,
6.25217499266303877725e-01, 6.25348141372440435859e-01,
6.25478766413446463091e-01, 6.25609374393779726908e-01,
6.25739965317896107422e-01, 6.25870539190249819406e-01,
6.26001096015293301278e-01, 6.26131635797477215100e-01,
6.26262158541250557597e-01, 6.26392664251060549141e-01,
6.26523152931352744766e-01, 6.26653624586570812127e-01,
6.26784079221156642525e-01, 6.26914516839550683969e-01,
6.27044937446191386066e-01, 6.27175341045515533089e-01,
6.27305727641958132956e-01, 6.27436097239952639271e-01,
6.27566449843930396213e-01, 6.27696785458321526718e-01,
6.27827104087553933276e-01, 6.27957405736054186107e-01,
6.28087690408246857032e-01, 6.28217958108554741514e-01,
6.28348208841399302749e-01, 6.28478442611199783485e-01,
6.28608659422374094206e-01, 6.28738859279338258013e-01,
6.28869042186506410630e-01, 6.28999208148291244491e-01,
6.29129357169103564651e-01, 6.29259489253352510829e-01,
6.29389604405445557411e-01, 6.29519702629788291404e-01,
6.29649783930784745500e-01, 6.29779848312837065016e-01,
6.29909895780345951977e-01, 6.30039926337710110005e-01,
6.30169939989326688412e-01, 6.30299936739590949131e-01,
6.30429916592896710803e-01, 6.30559879553635904692e-01,
6.30689825626198685704e-01, 6.30819754814973654433e-01,
6.30949667124347746139e-01, 6.31079562558705897679e-01,
6.31209441122431491600e-01, 6.31339302819906356135e-01,
6.31469147655510432138e-01, 6.31598975633622106152e-01,
6.31728786758617766317e-01, 6.31858581034872357485e-01,
6.31988358466759159171e-01, 6.32118119058649563513e-01,
6.32247862814913297314e-01, 6.32377589739918422040e-01,
6.32507299838031444850e-01, 6.32636993113616874496e-01,
6.32766669571037776443e-01, 6.32896329214655439799e-01,
6.33025972048829377314e-01, 6.33155598077917547428e-01,
6.33285207306276021200e-01, 6.33414799738259315376e-01,
6.33544375378220392392e-01, 6.33673934230510105259e-01,
6.33803476299478196765e-01, 6.33933001589472078230e-01,
6.34062510104837939728e-01, 6.34192001849920194978e-01,
6.34321476829061370317e-01, 6.34450935046602548795e-01,
6.34580376506882926080e-01, 6.34709801214240143530e-01,
6.34839209173010177167e-01, 6.34968600387527226658e-01,
6.35097974862123937356e-01, 6.35227332601131067236e-01,
6.35356673608877819959e-01, 6.35485997889691733853e-01,
6.35615305447898681912e-01, 6.35744596287822760772e-01,
6.35873870413786512756e-01, 6.36003127830110703833e-01,
6.36132368541114545657e-01, 6.36261592551115362504e-01,
6.36390799864429035360e-01, 6.36519990485369668853e-01,
6.36649164418249702280e-01, 6.36778321667379798576e-01,
6.36907462237069177391e-01, 6.37036586131625282015e-01,
6.37165693355353779381e-01, 6.37294783912558782113e-01,
6.37423857807542737497e-01, 6.37552915044606427486e-01,
6.37681955628048968698e-01, 6.37810979562167701395e-01,
6.37939986851258411527e-01, 6.38068977499615330728e-01,
6.38197951511530692237e-01, 6.38326908891295508042e-01,
6.38455849643198680710e-01, 6.38584773771527891562e-01,
6.38713681280568712495e-01, 6.38842572174605605184e-01,
6.38971446457920699835e-01, 6.39100304134795127453e-01,
6.39229145209507909620e-01, 6.39357969686336624626e-01,
6.39486777569557185430e-01, 6.39615568863443728631e-01,
6.39744343572268947540e-01, 6.39873101700303648087e-01,
6.40001843251817081892e-01, 6.40130568231077057284e-01,
6.40259276642349384190e-01, 6.40387968489898540270e-01,
6.40516643777987004782e-01, 6.40645302510875924717e-01,
6.40773944692824781733e-01, 6.40902570328091170104e-01,
6.41031179420931240820e-01, 6.41159771975599590554e-01,
6.41288347996348928604e-01, 6.41416907487430409951e-01,
6.41545450453093524246e-01, 6.41673976897586428869e-01,
6.41802486825155171779e-01, 6.41930980240044468665e-01,
6.42059457146497258861e-01, 6.42187917548755038410e-01,
6.42316361451057304954e-01, 6.42444788857642334889e-01,
6.42573199772746628256e-01, 6.42701594200604797713e-01,
6.42829972145450234677e-01, 6.42958333611514443184e-01,
6.43086678603027261936e-01, 6.43215007124217197365e-01,
6.43343319179310868527e-01, 6.43471614772533229143e-01,
6.43599893908107678620e-01, 6.43728156590256284098e-01,
6.43856402823198892271e-01, 6.43984632611154350634e-01,
6.44112845958339397257e-01, 6.44241042868969437940e-01,
6.44369223347258102130e-01, 6.44497387397417575983e-01,
6.44625535023658158273e-01, 6.44753666230188704489e-01,
6.44881781021216515803e-01, 6.45009879400947228056e-01,
6.45137961373584700731e-01, 6.45266026943331350019e-01,
6.45394076114387926779e-01, 6.45522108890953627558e-01,
6.45650125277225872544e-01, 6.45778125277400638637e-01,
6.45906108895672126380e-01, 6.46034076136233315069e-01,
6.46162027003274963555e-01, 6.46289961500986720466e-01,
6.46417879633556458074e-01, 6.46545781405170272294e-01,
6.46673666820013037793e-01, 6.46801535882267741862e-01,
6.46929388596115706456e-01, 6.47057224965736921263e-01,
6.47185044995309599614e-01, 6.47312848689010289505e-01,
6.47440636051014095642e-01, 6.47568407085494457398e-01,
6.47696161796623148810e-01, 6.47823900188570500625e-01,
6.47951622265505067233e-01, 6.48079328031593959736e-01,
6.48207017491002623899e-01, 6.48334690647894840154e-01,
6.48462347506432945643e-01, 6.48589988070777501150e-01,
6.48717612345087624171e-01, 6.48845220333520877887e-01,
6.48972812040233049125e-01, 6.49100387469378481420e-01,
6.49227946625109852974e-01, 6.49355489511578287676e-01,
6.49483016132933244080e-01, 6.49610526493322737451e-01,
6.49738020596893228742e-01, 6.49865498447789291525e-01,
6.49992960050154167106e-01, 6.50120405408129542479e-01,
6.50247834525855328280e-01, 6.50375247407469991856e-01,
6.50502644057110446241e-01, 6.50630024478911828112e-01,
6.50757388677007941880e-01, 6.50884736655530926619e-01,
6.51012068418611256071e-01, 6.51139383970377849664e-01,
6.51266683314958072515e-01, 6.51393966456477846450e-01,
6.51521233399061316938e-01, 6.51648484146831186159e-01,
6.51775718703908490959e-01, 6.51902937074412824892e-01,
6.52030139262461894134e-01, 6.52157325272172294639e-01,
6.52284495107658734980e-01, 6.52411648773034480442e-01,
6.52538786272411130973e-01, 6.52665907609898732211e-01,
6.52793012789605997526e-01, 6.52920101815639641885e-01,
6.53047174692105159011e-01, 6.53174231423106488315e-01,
6.53301272012745681828e-01, 6.53428296465123459313e-01,
6.53555304784339097246e-01, 6.53682296974490095742e-01,
6.53809273039672400607e-01, 6.53936232983980625377e-01,
6.54063176811507496211e-01, 6.54190104526344406999e-01,
6.54317016132581086296e-01, 6.54443911634305819369e-01,
6.54570791035605337171e-01, 6.54697654340564483277e-01,
6.54824501553267102061e-01, 6.54951332677795039494e-01,
6.55078147718228809282e-01, 6.55204946678647148772e-01,
6.55331729563127685090e-01, 6.55458496375745935936e-01,
6.55585247120576197766e-01, 6.55711981801691323746e-01,
6.55838700423162279662e-01, 6.55965402989058699035e-01,
6.56092089503448661070e-01, 6.56218759970398801684e-01,
6.56345414393973758393e-01, 6.56472052778237280535e-01,
6.56598675127251008021e-01, 6.56725281445075359521e-01,
6.56851871735769199390e-01, 6.56978446003389615626e-01,
6.57105004251992363962e-01, 6.57231546485631645815e-01,
6.57358072708359997272e-01, 6.57484582924228733170e-01,
6.57611077137287058925e-01, 6.57737555351583291774e-01,
6.57864017571163861575e-01, 6.57990463800073532852e-01,
6.58116894042355848882e-01, 6.58243308302052687608e-01,
6.58369706583204372663e-01, 6.58496088889849673365e-01,
6.58622455226025915742e-01, 6.58748805595768760490e-01,
6.58875140003112647058e-01, 6.59001458452090016493e-01,
6.59127760946732199621e-01, 6.59254047491068750908e-01,
6.59380318089127781533e-01, 6.59506572744935959385e-01,
6.59632811462518287016e-01, 6.59759034245898212667e-01,
6.59885241099097852313e-01, 6.60011432026137656592e-01,
6.60137607031036632854e-01, 6.60263766117812123113e-01,
6.60389909290480248139e-01, 6.60516036553055130298e-01,
6.60642147909550003781e-01, 6.60768243363975882332e-01,
6.60894322920342891514e-01, 6.61020386582659269514e-01,
6.61146434354931700206e-01, 6.61272466241165757239e-01,
6.61398482245365015864e-01, 6.61524482371531830083e-01,
6.61650466623666999588e-01, 6.61776435005769658737e-01,
6.61902387521837720641e-01, 6.62028324175867211032e-01,
6.62154244971853045421e-01, 6.62280149913788362959e-01,
6.62406039005664859509e-01, 6.62531912251472676623e-01,
6.62657769655200512560e-01, 6.62783611220835733313e-01,
6.62909436952363706475e-01, 6.63035246853768911457e-01,
6.63161040929033829272e-01, 6.63286819182139719686e-01,
6.63412581617066288153e-01, 6.63538328237791463771e-01,
6.63664059048292176435e-01, 6.63789774052543579685e-01,
6.63915473254519050705e-01, 6.64041156658191078499e-01,
6.64166824267530264692e-01, 6.64292476086505656596e-01,
6.64418112119084969258e-01, 6.64543732369234474433e-01,
6.64669336840918778542e-01, 6.64794925538101155738e-01,
6.64920498464743214839e-01, 6.65046055624805232398e-01,
6.65171597022245819630e-01, 6.65297122661022366508e-01,
6.65422632545090486644e-01, 6.65548126678404461387e-01,
6.65673605064917017771e-01, 6.65799067708579439540e-01,
6.65924514613341678171e-01, 6.66049945783151686740e-01,
6.66175361221956641167e-01, 6.66300760933701607946e-01,
6.66426144922330543352e-01, 6.66551513191785738321e-01,
6.66676865746008262548e-01, 6.66802202588937187322e-01,
6.66927523724510695757e-01, 6.67052829156665194610e-01,
6.67178118889335536323e-01, 6.67303392926455130052e-01,
6.67428651271956163704e-01, 6.67553893929769048832e-01,
6.67679120903822864719e-01, 6.67804332198045247360e-01,
6.67929527816362167414e-01, 6.68054707762698263274e-01,
6.68179872040976619019e-01, 6.68305020655119097484e-01,
6.68430153609045785146e-01, 6.68555270906675325193e-01,
6.68680372551925139568e-01, 6.68805458548710873856e-01,
6.68930528900946952398e-01, 6.69055583612546245220e-01,
6.69180622687419957018e-01, 6.69305646129478182260e-01,
6.69430653942629239062e-01, 6.69555646130780224290e-01,
6.69680622697836569479e-01, 6.69805583647702484917e-01,
6.69930528984280293514e-01, 6.70055458711471318978e-01,
6.70180372833175219682e-01, 6.70305271353290099690e-01,
6.70430154275712841816e-01, 6.70555021604338552521e-01,
6.70679873343061228042e-01, 6.70804709495773088257e-01,
6.70929530066365131802e-01, 6.71054335058726802998e-01,
6.71179124476746102879e-01, 6.71303898324309589185e-01,
6.71428656605302376370e-01, 6.71553399323607913551e-01,
6.71678126483108539624e-01, 6.71802838087684928148e-01,
6.71927534141216420416e-01, 6.72052214647580803408e-01,
6.72176879610654420816e-01, 6.72301529034312284061e-01,
6.72426162922427739232e-01, 6.72550781278872911173e-01,
6.72675384107518370413e-01, 6.72799971412233133172e-01,
6.72924543196884994423e-01, 6.73049099465340305848e-01,
6.73173640221463642774e-01, 6.73298165469118470305e-01,
6.73422675212166699232e-01, 6.73547169454468797056e-01,
6.73671648199883787989e-01, 6.73796111452269252950e-01,
6.73920559215481329574e-01, 6.74044991493374712199e-01,
6.74169408289802651879e-01, 6.74293809608617067397e-01,
6.74418195453668323225e-01, 6.74542565828805340544e-01,
6.74666920737875597247e-01, 6.74791260184725238958e-01,
6.74915584173198968010e-01, 6.75039892707139821404e-01,
6.75164185790389836939e-01, 6.75288463426789165034e-01,
6.75412725620176734864e-01, 6.75536972374390143337e-01,
6.75661203693265322023e-01, 6.75785419580636981252e-01,
6.75909620040338388058e-01, 6.76033805076201144146e-01,
6.76157974692055740995e-01, 6.76282128891731004749e-01,
6.76406267679054540309e-01, 6.76530391057852287240e-01,
6.76654499031948852839e-01, 6.76778591605167623158e-01,
6.76902668781330207892e-01, 6.77026730564257217537e-01,
6.77150776957767375208e-01, 6.77274807965678293797e-01,
6.77398823591806142908e-01, 6.77522823839965537829e-01,
6.77646808713969761584e-01, 6.77770778217630653906e-01,
6.77894732354758722259e-01, 6.78018671129162808775e-01,
6.78142594544650756383e-01, 6.78266502605028631656e-01,
6.78390395314101168900e-01, 6.78514272675671770152e-01,
6.78638134693542394160e-01, 6.78761981371513556383e-01,
6.78885812713384440009e-01, 6.79009628722952562896e-01,
6.79133429404014443698e-01, 6.79257214760364935735e-01,
6.79380984795797338016e-01, 6.79504739514103950349e-01,
6.79628478919075296183e-01, 6.79752203014500677725e-01,
6.79875911804167953889e-01, 6.79999605291863540302e-01,
6.80123283481372520320e-01, 6.80246946376478422991e-01,
6.80370593980963667136e-01, 6.80494226298608895220e-01,
6.80617843333193639488e-01, 6.80741445088495988891e-01,
6.80865031568292367048e-01, 6.80988602776358198376e-01,
6.81112158716467130937e-01, 6.81235699392391813589e-01,
6.81359224807903118837e-01, 6.81482734966770586915e-01,
6.81606229872762758859e-01, 6.81729709529646177302e-01,
6.81853173941186385676e-01, 6.81976623111147484124e-01,
6.82100057043292129499e-01, 6.82223475741381535364e-01,
6.82346879209175583014e-01, 6.82470267450432710454e-01,
6.82593640468910134445e-01, 6.82716998268363406410e-01,
6.82840340852546967554e-01, 6.82963668225213593743e-01,
6.83086980390114839601e-01, 6.83210277351001038504e-01,
6.83333559111620636450e-01, 6.83456825675721302282e-01,
6.83580077047048817462e-01, 6.83703313229347853230e-01,
6.83826534226361637536e-01, 6.83949740041831955040e-01,
6.84072930679499369155e-01, 6.84196106143102777963e-01,
6.84319266436379969321e-01, 6.84442411563067176772e-01,
6.84565541526899412617e-01, 6.84688656331610134842e-01,
6.84811755980931580190e-01, 6.84934840478594542112e-01,
6.85057909828328370772e-01, 6.85180964033861084062e-01,
6.85304003098919367609e-01, 6.85427027027228574774e-01,
6.85550035822512615624e-01, 6.85673029488493845918e-01,
6.85796008028893511188e-01, 6.85918971447431524702e-01,
6.86041919747826134390e-01, 6.86164852933794477963e-01,
6.86287771009052138815e-01, 6.86410673977313590122e-01,
6.86533561842291528698e-01, 6.86656434607697763184e-01,
6.86779292277242214837e-01, 6.86902134854634027761e-01,
6.87024962343580458679e-01, 6.87147774747787654093e-01,
6.87270572070960317212e-01, 6.87393354316801818982e-01,
6.87516121489014198076e-01, 6.87638873591298049881e-01,
6.87761610627352748537e-01, 6.87884332600876113872e-01,
6.88007039515564633447e-01, 6.88129731375113684599e-01,
6.88252408183216979332e-01, 6.88375069943567119424e-01,
6.88497716659855041321e-01, 6.88620348335770571246e-01,
6.88742964975002092132e-01, 6.88865566581236654642e-01,
6.88988153158160088196e-01, 6.89110724709456445858e-01,
6.89233281238809003533e-01, 6.89355822749899149748e-01,
6.89478349246407273831e-01, 6.89600860732012321819e-01,
6.89723357210391685435e-01, 6.89845838685221757203e-01,
6.89968305160177375335e-01, 6.90090756638931934752e-01,
6.90213193125157720154e-01, 6.90335614622525572948e-01,
6.90458021134704891253e-01, 6.90580412665363740921e-01,
6.90702789218168966556e-01, 6.90825150796785969476e-01,
6.90947497404878929750e-01, 6.91069829046110473136e-01,
6.91192145724142004148e-01, 6.91314447442633595031e-01,
6.91436734205243874740e-01, 6.91559006015630362008e-01,
6.91681262877449021254e-01, 6.91803504794354484631e-01,
6.91925731770000163046e-01, 6.92047943808038024116e-01,
6.92170140912118703191e-01, 6.92292323085891614376e-01,
6.92414490333004617462e-01, 6.92536642657104462018e-01,
6.92658780061836454323e-01, 6.92780902550844568388e-01,
6.92903010127771445958e-01, 6.93025102796258285487e-01,
6.93147180559945286227e-01
};
static const double fm_log_q2[] = {
-9.99999970204339394542e-01, -9.99511867731007974669e-01,
-9.99024122545299819720e-01, -9.98536734292937211421e-01,
-9.98049702617656908643e-01, -9.97563027181486594586e-01,
-9.97076707618930857535e-01, -9.96590743612639662352e-01,
-9.96105134789343704682e-01, -9.95619880820340474870e-01,
-9.95134981341887603357e-01, -9.94650436042181285146e-01,
-9.94166244524016029516e-01, -9.93682406505230209071e-01,
-9.93198921590821237615e-01, -9.92715789460176134540e-01,
-9.92233009782583330605e-01, -9.91750582106026845608e-01,
-9.91268506386495218408e-01, -9.90786781855067077984e-01,
-9.90305408488223459784e-01, -9.89824385926602934305e-01,
-9.89343713535692392824e-01, -9.88863391418940196331e-01,
-9.88383418923948875445e-01, -9.87903795762894443300e-01,
-9.87424521643993191589e-01, -9.86945596275973890954e-01,
-9.86467019194852801078e-01, -9.85988790103114798313e-01,
-9.85510908733950863336e-01, -9.85033374705881481503e-01,
-9.84556187716159159073e-01, -9.84079347261778369926e-01,
-9.83602853387407938257e-01, -9.83126705195018768535e-01,
-9.82650902914219859241e-01, -9.82175445826114934533e-01,
-9.81700333782709821939e-01, -9.81225566348648436943e-01,
-9.80751143317876161731e-01, -9.80277064203733838887e-01,
-9.79803328714193400018e-01, -9.79329936757795227464e-01,
-9.78856887595422442416e-01, -9.78384181131788044361e-01,
-9.77911817090174495526e-01, -9.77439794926507898865e-01,
-9.76968114649079621969e-01, -9.76496775371813452438e-01,
-9.76025777487512291586e-01, -9.75555119961791561423e-01,
-9.75084803046927794945e-01, -9.74614826069708173328e-01,
-9.74145188676739381961e-01, -9.73675890859331483185e-01,
-9.73206931957900756025e-01, -9.72738311825502188768e-01,
-9.72270029963272386375e-01, -9.71802086418131150225e-01,
-9.71334480453526993848e-01, -9.70867211825531484237e-01,
-9.70400280500180012488e-01, -9.69933685809522216914e-01,
-9.69467427665356984434e-01, -9.69001505342206970184e-01,
-9.68535919385462573672e-01, -9.68070668339039097638e-01,
-9.67605752941687047297e-01, -9.67141171694490986432e-01,
-9.66676925663408237455e-01, -9.66213013480509586017e-01,
-9.65749435360603869505e-01, -9.65286190415398870357e-01,
-9.64823279189289229052e-01, -9.64360700392987491014e-01,
-9.63898454448297248298e-01, -9.63436540957292031351e-01,
-9.62974958994398444467e-01, -9.62513709167376330100e-01,
-9.62052789970760380278e-01, -9.61592202627699954576e-01,
-9.61131945148046229477e-01, -9.60672018681310024846e-01,
-9.60212422016580413597e-01, -9.59753154657040807862e-01,
-9.59294217705390250828e-01, -9.58835608644634573849e-01,
-9.58377329455130544389e-01, -9.57919378224905693209e-01,
-9.57461755033558459260e-01, -9.57004460077683027919e-01,
-9.56547492491304551798e-01, -9.56090852049268358215e-01,
-9.55634538422690971160e-01, -9.55178551755278659741e-01,
-9.54722891102598336666e-01, -9.54267556606214206738e-01,
-9.53812547247320785537e-01, -9.53357864165607526985e-01,
-9.52903505218105184582e-01, -9.52449471550573356637e-01,
-9.51995762119929311851e-01, -9.51542377158775654067e-01,
-9.51089315382799949106e-01, -9.50636577505697299983e-01,
-9.50184162655493436134e-01, -9.49732070812421613759e-01,
-9.49280301530538883625e-01, -9.48828854517908548694e-01,
-9.48377729292745219603e-01, -9.47926925978650358751e-01,
-9.47476443864510908810e-01, -9.47026282877210912048e-01,
-9.46576442623344060934e-01, -9.46126922654174640215e-01,
-9.45677723062576136570e-01, -9.45228843227299053709e-01,
-9.44780282746499722180e-01, -9.44332041753326523192e-01,
-9.43884119418537004265e-01, -9.43436516131986646627e-01,
-9.42989230465001604387e-01, -9.42542263551472636607e-01,
-9.42095613681492860536e-01, -9.41649281671355309342e-01,
-9.41203266664289106558e-01, -9.40757568477113448324e-01,
-9.40312186603849187172e-01, -9.39867121156116924752e-01,
-9.39422371494921693014e-01, -9.38977937969146747577e-01,
-9.38533818425270727204e-01, -9.38090015540559929441e-01,
-9.37646526347406972235e-01, -9.37203351657070138359e-01,
-9.36760491192124566950e-01, -9.36317945251011529706e-01,
-9.35875711520406383670e-01, -9.35433791970248562642e-01,
-9.34992185225055116859e-01, -9.34550890625867491934e-01,
-9.34109909390034354182e-01, -9.33669238704104120785e-01,
-9.33228881619615147081e-01, -9.32788834331801042232e-01,
-9.32349099229301314651e-01, -9.31909674753276684456e-01,
-9.31470560559493843122e-01, -9.31031756789755693404e-01,
-9.30593263221085265080e-01, -9.30155079206603119246e-01,
-9.29717204762836368914e-01, -9.29279639073573582309e-01,
-9.28842382593162874116e-01, -9.28405434320425215766e-01,
-9.27968795011759772784e-01, -9.27532462642750910042e-01,
-9.27096438966723779274e-01, -9.26660721788762020701e-01,
-9.26225312547271695252e-01, -9.25790209080529336028e-01,
-9.25355413009083083153e-01, -9.24920922806437006969e-01,
-9.24486738767070992395e-01, -9.24052859842579898952e-01,
-9.23619287138135014459e-01, -9.23186018678442410490e-01,
-9.22753055671568844787e-01, -9.22320396657525742867e-01,
-9.21888042077250058348e-01, -9.21455991626982218179e-01,
-9.21024244683838921866e-01, -9.20592801249144221387e-01,
-9.20161660543504122955e-01, -9.19730822889199606252e-01,
-9.19300287776504854165e-01, -9.18870054128069879695e-01,
-9.18440123969056387843e-01, -9.18010494467117244000e-01,
-9.17581166544576887212e-01, -9.17152139344484806927e-01,
-9.16723413975333523140e-01, -9.16294988257087883454e-01,
-9.15866862816476667852e-01, -9.15439037326621463109e-01,
-9.15011512468304366585e-01, -9.14584285845278177618e-01,
-9.14157359376828626552e-01, -9.13730730576027161405e-01,
-9.13304401883368921489e-01, -9.12878370214750711753e-01,
-9.12452637084189110972e-01, -9.12027202313689278057e-01,
-9.11602063704228360308e-01, -9.11177223244973188976e-01,
-9.10752679369231765705e-01, -9.10328432163654999165e-01,
-9.09904481451345503729e-01, -9.09480826456257163137e-01,
-9.09057467665507212828e-01, -9.08634403906669829709e-01,
-9.08211636588364790157e-01, -9.07789162645522784700e-01,
-9.07366984547896548996e-01, -9.06945101069483228251e-01,
-9.06523510453585923408e-01, -9.06102215365062191310e-01,
-9.05681212489113374176e-01, -9.05260504038174707020e-01,
-9.04840087271269188918e-01, -9.04419965351935140063e-01,
-9.04000133954933060565e-01, -9.03580596041809180896e-01,
-9.03161349679556746395e-01, -9.02742395447701850841e-01,
-9.02323731564164344121e-01, -9.01905360386788146343e-01,
-9.01487278457227647621e-01, -9.01069488869118639940e-01,
-9.00651988294198790896e-01, -9.00234778569980020890e-01,
-8.99817858468642706171e-01, -8.99401228269987029762e-01,
-8.98984886685647799354e-01, -8.98568834398333571301e-01,
-8.98153071362558952373e-01, -8.97737595680574984591e-01,
-8.97322409400924114742e-01, -8.96907510418140430097e-01,
-8.96492899517607799709e-01, -8.96078575663256993167e-01,
-8.95664539420013672277e-01, -8.95250789564243198981e-01,
-8.94837326234608987363e-01, -8.94424150100090686877e-01,
-8.94011259743090591634e-01, -8.93598654577083761907e-01,
-8.93186335571800604782e-01, -8.92774302228811822424e-01,
-8.92362552778136142173e-01, -8.91951089210193392987e-01,
-8.91539909524236673377e-01, -8.91129014144898534688e-01,
-8.90718403374395006900e-01, -8.90308075579229751817e-01,
-8.89898031403237421699e-01, -8.89488271301558164339e-01,
-8.89078792809798290619e-01, -8.88669598345472655510e-01,
-8.88260684893865892775e-01, -8.87852055111406412991e-01,
-8.87443705578046637683e-01, -8.87035638935646852943e-01,
-8.86627853624748274441e-01, -8.86220349050373723543e-01,
-8.85813124960938669261e-01, -8.85406182957758969287e-01,
-8.84999519681124224846e-01, -8.84593137189672695797e-01,
-8.84187034799512772132e-01, -8.83781211790588994148e-01,
-8.83375667536064224095e-01, -8.82970403866355613154e-01,
-8.82565416880603970107e-01, -8.82160710572937767360e-01,
-8.81756281249608142581e-01, -8.81352129912593151850e-01,
-8.80948257644714738390e-01, -8.80544661906674352991e-01,
-8.80141343390940522617e-01, -8.79738301866938576801e-01,
-8.79335537564497671248e-01, -8.78933049794877185867e-01,
-8.78530838289241611250e-01, -8.78128902017706214345e-01,
-8.77727242574676602693e-01, -8.77325857406385578585e-01,
-8.76924749545558213093e-01, -8.76523915002998088575e-01,
-8.76123355526894909140e-01, -8.75723070907653888817e-01,
-8.75323060235463579204e-01, -8.74923324565198612390e-01,
-8.74523860587170576153e-01, -8.74124672103355093711e-01,
-8.73725755597443032308e-01, -8.73327112950790240831e-01,
-8.72928742948249847267e-01, -8.72530645775088542493e-01,
-8.72132819111415824587e-01, -8.71735266463592339825e-01,
-8.71337984507970064740e-01, -8.70940974650877608454e-01,
-8.70544234590646004435e-01, -8.70147769333657672419e-01,
-8.69751569537952962108e-01, -8.69355645213247596459e-01,
-8.68959988014379680621e-01, -8.68564601754506560027e-01,
-8.68169485114097416734e-01, -8.67774639558116844817e-01,
-8.67380060546237952046e-01, -8.66985753598933484021e-01,
-8.66591712350508802665e-01, -8.66197942773432094654e-01,
-8.65804438519395369589e-01, -8.65411205039324338273e-01,
-8.65018238053694155099e-01, -8.64625538053809039596e-01,
-8.64233107353976737208e-01, -8.63840941793596828191e-01,
-8.63449044524892350694e-01, -8.63057412687507463644e-01,
-8.62666048982706823445e-01, -8.62274948259755036339e-01,
-8.61884117244458014540e-01, -8.61493548154168120590e-01,
-8.61103248629860429375e-01, -8.60713209860124339734e-01,
-8.60323439891849783834e-01, -8.59933932112696530758e-01,
-8.59544690955295176416e-01, -8.59155710889400126007e-01,
-8.58766998427491934365e-01, -8.58378547019733151302e-01,
-8.57990359589185458411e-01, -8.57602436581375471292e-01,
-8.57214776085103435932e-01, -8.56827376917738359197e-01,
-8.56440242927035244591e-01, -8.56053368286509908103e-01,
-8.55666758484504463844e-01, -8.55280408570004979651e-01,
-8.54894321682854507749e-01, -8.54508495802631440341e-01,
-8.54122930283242931537e-01, -8.53737626935513915782e-01,
-8.53352581956205002989e-01, -8.52967800365546313657e-01,
-8.52583277061727651258e-01, -8.52199013461921284218e-01,
-8.51815011793214615921e-01, -8.51431267318022655388e-01,
-8.51047782789758122668e-01, -8.50664557520292130555e-01,
-8.50281591508726952711e-01, -8.49898882652814657845e-01,
-8.49516433774509360788e-01, -8.49134241276175760760e-01,
-8.48752308344500772108e-01, -8.48370631418307152849e-01,
-8.47989213173712008675e-01, -8.47608052055359939558e-01,
-8.47227146020622434719e-01, -8.46846499207430714051e-01,
-8.46466108282560192322e-01, -8.46085971265107983363e-01,
-8.45706093823972659962e-01, -8.45326469234303878864e-01,
-8.44947101962797320063e-01, -8.44567989249422446107e-01,
-8.44189132079671167297e-01, -8.43810529271607157042e-01,
-8.43432181773515310397e-01, -8.43054086974192373738e-01,
-8.42676248782231018808e-01, -8.42298662556367427889e-01,
-8.41921331777192527568e-01, -8.41544252751542209978e-01,
-8.41167428389579807657e-01, -8.40790856331749880681e-01,
-8.40414537518176185671e-01, -8.40038470547919358111e-01,
-8.39662657290645486619e-01, -8.39287094462596861000e-01,
-8.38911784947234617782e-01, -8.38536726082408478966e-01,
-8.38161920045321418016e-01, -8.37787363583282096435e-01,
-8.37413059147947502758e-01, -8.37039005773316913128e-01,
-8.36665202077768510591e-01, -8.36291648965855838327e-01,
-8.35918346994952599083e-01, -8.35545293031011770957e-01,
-8.35172490670944567270e-01, -8.34799937043055217956e-01,
-8.34427631655312529446e-01, -8.34055576553571542675e-01,
-8.33683769634376070634e-01, -8.33312211677761704998e-01,
-8.32940901667041044831e-01, -8.32569840094962154708e-01,
-8.32199026007219733181e-01, -8.31828459934317754332e-01,
-8.31458140708547288611e-01, -8.31088069676270801978e-01,
-8.30718245413716971370e-01, -8.30348666681671510048e-01,
-8.29979337066795830324e-01, -8.29610251843562407359e-01,
-8.29241412357579754655e-01, -8.28872820745909844042e-01,
-8.28504472702632721592e-01, -8.28136372138494003536e-01,
-8.27768516098335127573e-01, -8.27400904110141666159e-01,
-8.27033538223160613612e-01, -8.26666416300355200164e-01,
-8.26299539252689507762e-01, -8.25932905573345754746e-01,
-8.25566517584661041518e-01, -8.25200370298072694020e-01,
-8.24834470169624522917e-01, -8.24468810333541246571e-01,
-8.24103395033075170062e-01, -8.23738222542895748290e-01,
-8.23373292727103800459e-01, -8.23008605060659648167e-01,
-8.22644158985652573790e-01, -8.22279957258766014405e-01,
-8.21915994999112275998e-01, -8.21552275003720078317e-01,
-8.21188796553297462033e-01, -8.20825559727983877778e-01,
-8.20462562132544981353e-01, -8.20099807679844250430e-01,
-8.19737291495564845967e-01, -8.19375017988239751077e-01,
-8.19012982779956599799e-01, -8.18651187797961865655e-01,
-8.18289632505148967212e-01, -8.17928317122697978725e-01,
-8.17567241302996294827e-01, -8.17206403421344873550e-01,
-8.16845804736217262487e-01, -8.16485444632387147301e-01,
-8.16125324312285349571e-01, -8.15765439581415341408e-01,
-8.15405794839461406376e-01, -8.15046387858052834297e-01,
-8.14687217563053955871e-01, -8.14328284891442821802e-01,
-8.13969589963410289357e-01, -8.13611131361214212632e-01,
-8.13252909047697203349e-01, -8.12894924589232403811e-01,
-8.12537174551450025461e-01, -8.12179662723554018910e-01,
-8.11822385765001985902e-01, -8.11465344866855842199e-01,
-8.11108538605410545053e-01, -8.10751968690456070732e-01,
-8.10395632500506502005e-01, -8.10039533223778640547e-01,
-8.09683666316827421738e-01, -8.09328035589345851086e-01,
-8.08972638727908588407e-01, -8.08617475588590539637e-01,
-8.08262546266548476126e-01, -8.07907850525080184489e-01,
-8.07553389215838191006e-01, -8.07199159168914714968e-01,
-8.06845163830385736503e-01, -8.06491400967756844054e-01,
-8.06137870476995033187e-01, -8.05784572212759564458e-01,
-8.05431506860445400875e-01, -8.05078671823814207009e-01,
-8.04726071214487803651e-01, -8.04373699564121635852e-01,
-8.04021560664633705429e-01, -8.03669653198598288313e-01,
-8.03317975849833776358e-01, -8.02966529612556545459e-01,
-8.02615314620049424832e-01, -8.02264329344965387847e-01,
-8.01913574175475818429e-01, -8.01563049086241208308e-01,
-8.01212753790446652324e-01, -8.00862689460692500631e-01,
-8.00512851693393034935e-01, -8.00163245754418328559e-01,
-7.99813866159745590068e-01, -7.99464718403725238538e-01,
-7.99115797168848507326e-01, -7.98767104260962645945e-01,
-7.98418640568153703541e-01, -7.98070403526198957067e-01,
-7.97722396915967246755e-01, -7.97374613766141382420e-01,
-7.97027061417315940695e-01, -7.96679734242235038089e-01,
-7.96332636233457291652e-01, -7.95985762635938898235e-01,
-7.95639117301425558004e-01, -7.95292697959882555203e-01,
-7.94946504251766716820e-01, -7.94600537091318392946e-01,
-7.94254795975086080873e-01, -7.93909279208667828520e-01,
-7.93563988485189275579e-01, -7.93218924314483708748e-01,
-7.92874082964091897452e-01, -7.92529467678147581111e-01,
-7.92185077594477093932e-01, -7.91840910123675190135e-01,
-7.91496968103633014024e-01, -7.91153251154092851394e-01,
-7.90809755164228800339e-01, -7.90466485781729399918e-01,
-7.90123438496507235485e-01, -7.89780614525349644595e-01,
-7.89438013511196468031e-01, -7.89095635665502115330e-01,
-7.88753480499506887114e-01, -7.88411546962827891605e-01,
-7.88069836951789781665e-01, -7.87728349519411286117e-01,
-7.87387080969357722182e-01, -7.87046038652046253681e-01,
-7.86705213625948918121e-01, -7.86364611955018277811e-01,
-7.86024232294810998312e-01, -7.85684071165180464291e-01,
-7.85344132655284687949e-01, -7.85004415064510130406e-01,
-7.84664915518216821155e-01, -7.84325638833675120587e-01,
-7.83986579792315119164e-01, -7.83647743275274089036e-01,
-7.83309123358476799837e-01, -7.82970724887247948587e-01,
-7.82632545580235650107e-01, -7.82294584129585413024e-01,
-7.81956842460133971784e-01, -7.81619319768323217446e-01,
-7.81282014549579795215e-01, -7.80944928037821894939e-01,
-7.80608059595917502804e-01, -7.80271410538476040131e-01,
-7.79934976244191724426e-01, -7.79598762707806702821e-01,
-7.79262764541498231807e-01, -7.78926983331975741898e-01,
-7.78591420914192311464e-01, -7.78256073949561311132e-01,
-7.77920942781604729532e-01, -7.77586029374822684801e-01,
-7.77251331115626831192e-01, -7.76916850905936318128e-01,
-7.76582585339597120111e-01, -7.76248533963435183303e-01,
-7.75914701996302635933e-01, -7.75581080191833582838e-01,
-7.75247677964898906922e-01, -7.74914489254122762496e-01,
-7.74581512126330751222e-01, -7.74248754787661197518e-01,
-7.73916208698477214867e-01, -7.73583877459445679037e-01,
-7.73251760795472087295e-01, -7.72919856206266908671e-01,
-7.72588168380147766179e-01, -7.72256692240005038208e-01,
-7.71925426642152245904e-01, -7.71594381238445370386e-01,
-7.71263540916888867827e-01, -7.70932917358060021407e-01,
-7.70602506891323590921e-01, -7.70272306930707917338e-01,
-7.69942320314862649333e-01, -7.69612543863097631203e-01,
-7.69282981871587834277e-01, -7.68953631512193758191e-01,
-7.68624488625428980981e-01, -7.68295561501506463209e-01,
-7.67966843490803574568e-01, -7.67638336137790866509e-01,
-7.67310039914208652512e-01, -7.66981956976561352057e-01,
-7.66654078227090418629e-01, -7.66326415548583939064e-01,
-7.65998958447325462018e-01, -7.65671714663651137300e-01,
-7.65344680493737494764e-01, -7.65017851836673590249e-01,
-7.64691237624055331068e-01, -7.64364828582150601655e-01,
-7.64038630522551276414e-01, -7.63712640648493090723e-01,
-7.63386858747504670752e-01, -7.63061288466236553596e-01,
-7.62735921018492635248e-01, -7.62410765550665892043e-01,
-7.62085816615121647288e-01, -7.61761075680135402166e-01,
-7.61436542320239606596e-01, -7.61112216769028959718e-01,
-7.60788098517591659942e-01, -7.60464183780045210881e-01,
-7.60140482620896840160e-01, -7.59816980919740148082e-01,
-7.59493691566082151923e-01, -7.59170605061977532557e-01,
-7.58847724157959091507e-01, -7.58525052937777277684e-01,
-7.58202583491767168056e-01, -7.57880321023096881206e-01,
-7.57558263804628873039e-01, -7.57236413541746422595e-01,
-7.56914765140053291681e-01, -7.56593326095880147619e-01,
-7.56272088282107901591e-01, -7.55951054359139007488e-01,
-7.55630227400418519323e-01, -7.55309603627635328671e-01,
-7.54989183904718030860e-01, -7.54668968554262464821e-01,
-7.54348955421957012568e-01, -7.54029147214517081466e-01,
-7.53709540847328773872e-01, -7.53390140364195159961e-01,
-7.53070938262454747658e-01, -7.52751943745142870767e-01,
-7.52433149854522587141e-01, -7.52114558454699100309e-01,
-7.51796169046989537499e-01, -7.51477981762019409118e-01,
-7.51159996575969213239e-01, -7.50842213453493112496e-01,
-7.50524632559792070907e-01, -7.50207253269409068963e-01,
-7.49890072331035217879e-01, -7.49573097787428865857e-01,
-7.49256317482670186614e-01, -7.48939744058004119864e-01,
-7.48623367044046972296e-01, -7.48307193325348007917e-01,
-7.47991217008963427126e-01, -7.47675443606249379158e-01,
-7.47359868140595740016e-01, -7.47044493831215072888e-01,
-7.46729318365803806934e-01, -7.46414342186427659520e-01,
-7.46099565837127109980e-01, -7.45784986699675633837e-01,
-7.45470609115002180722e-01, -7.45156429513488927086e-01,
-7.44842446656806989047e-01, -7.44528663479954389004e-01,
-7.44215080657139260722e-01, -7.43901692556530491629e-01,
-7.43588504267438610285e-01, -7.43275512240322511204e-01,
-7.42962719996102194386e-01, -7.42650122588572991766e-01,
-7.42337725105762458178e-01, -7.42025523317636936937e-01,
-7.41713517880432493534e-01, -7.41401710399238300653e-01,
-7.41090099385395939535e-01, -7.40778683600515686081e-01,
-7.40467463898880073891e-01, -7.40156443689682697062e-01,
-7.39845614069802537394e-01, -7.39534984890788393841e-01,
-7.39224548001308101597e-01, -7.38914309391334400701e-01,
-7.38604264428180834479e-01, -7.38294414476748039888e-01,
-7.37984758710120813952e-01, -7.37675299071058887534e-01,
-7.37366034203374987044e-01, -7.37056962001121251937e-01,
-7.36748086656342393574e-01, -7.36439404682677878355e-01,
-7.36130914657654233935e-01, -7.35822620169590324579e-01,
-7.35514519463555171974e-01, -7.35206610383018932531e-01,
-7.34898897721095401003e-01, -7.34591375637730692461e-01,
-7.34284045936220541861e-01, -7.33976912831370453816e-01,
-7.33669968836534902579e-01, -7.33363217331747141436e-01,
-7.33056663459391577575e-01, -7.32750294445768779461e-01,
-7.32444122715677270463e-01, -7.32138139283301514482e-01,
-7.31832350903298456402e-01, -7.31526750718727192258e-01,
-7.31221342638886384613e-01, -7.30916129059394292788e-01,
-7.30611102076414442585e-01, -7.30306268557933346841e-01,
-7.30001625699647327394e-01, -7.29697172262848026136e-01,
-7.29392910418738549261e-01, -7.29088838309150055750e-01,
-7.28784955607618689655e-01, -7.28481265478169826011e-01,
-7.28177761179099825029e-01, -7.27874449749392971043e-01,
-7.27571326538621221403e-01, -7.27268391933642233127e-01,
-7.26965649037452310566e-01, -7.26663090639144915173e-01,
-7.26360725715543331660e-01, -7.26058547922002528452e-01,
-7.25756556896473670193e-01, -7.25454754843860794011e-01,
-7.25153144482468259291e-01, -7.24851718322109705994e-01,
-7.24550481253484202071e-01, -7.24249432379852731145e-01,
-7.23948570397473178950e-01, -7.23647895830116794080e-01,
-7.23347407886440363356e-01, -7.23047109208045823969e-01,
-7.22746995607804532114e-01, -7.22447070016758230437e-01,
-7.22147330485803817801e-01, -7.21847776292375953311e-01,
-7.21548412275839101682e-01, -7.21249230977172972601e-01,
-7.20950235041350917520e-01, -7.20651426935435934773e-01,
-7.20352805322073797001e-01, -7.20054367495683189659e-01,
-7.19756114440071592675e-01, -7.19458050513526736758e-01,
-7.19160168474960670437e-01, -7.18862470578696011181e-01,
-7.18564960636466132371e-01, -7.18267632322884708174e-01,
-7.17970490363957880575e-01, -7.17673533356917969783e-01,
-7.17376756598895437556e-01, -7.17080169128263444911e-01,
-7.16783761846141453944e-01, -7.16487539757937441642e-01,
-7.16191503116768934945e-01, -7.15895645904759847511e-01,
-7.15599975176490210593e-01, -7.15304485495321218380e-01,
-7.15009180377358166680e-01, -7.14714056782754569852e-01,
-7.14419117766853850604e-01, -7.14124359736066027793e-01,
-7.13829782833535930742e-01, -7.13535390080274445346e-01,
-7.13241180424964205109e-01, -7.12947149463927454249e-01,
-7.12653304687322797228e-01, -7.12359637301999693015e-01,
-7.12066152638659022323e-01, -7.11772849343519586895e-01,
-7.11479727501005188017e-01, -7.11186788127201818810e-01,
-7.10894027073341483458e-01, -7.10601448742539276715e-01,
-7.10309050846974154858e-01, -7.10016832546879306243e-01,
-7.09724793901207129387e-01, -7.09432935513915619019e-01,
-7.09141260498156178471e-01, -7.08849761385299537153e-01,
-7.08558442584971137634e-01, -7.08267305103167377212e-01,
-7.07976346094213448978e-01, -7.07685564758942065033e-01,
-7.07394967139696184688e-01, -7.07104541042143486251e-01,
-7.06814301261591060310e-01, -7.06524234338757661789e-01,
-7.06234351375782054561e-01, -7.05944643775133773289e-01,
-7.05655112473053125477e-01, -7.05365762322110345650e-01,
-7.05076589739588643901e-01, -7.04787593027915937327e-01,
-7.04498776972161788734e-01, -7.04210135305489814961e-01,
-7.03921671546370086858e-01, -7.03633389063629932636e-01,
-7.03345276451424861186e-01, -7.03057348024629158445e-01,
-7.02769591457201636686e-01, -7.02482013798756299572e-01,
-7.02194610352749770676e-01, -7.01907387267804994124e-01,
-7.01620335821844576252e-01, -7.01333462402813800907e-01,
-7.01046766944815602507e-01, -7.00760243323492182377e-01,
-7.00473899338366345901e-01, -7.00187726679509570005e-01,
-6.99901734023308352839e-01, -6.99615911737950901816e-01,
-6.99330267322555876319e-01, -6.99044797176266552441e-01,
-6.98759502615456606911e-01, -6.98474381975487834673e-01,
-6.98189435010603598464e-01, -6.97904664368468763413e-01,
-6.97620065292115398847e-01, -6.97335642985881021261e-01,
-6.97051392565252503353e-01, -6.96767317188075163692e-01,
-6.96483414695416080953e-01, -6.96199684977226063154e-01,
-6.95916130632634022390e-01, -6.95632746963111059380e-01,
-6.95349538987770743326e-01, -6.95066502504559258213e-01,
-6.94783638126708624760e-01, -6.94500947603343021797e-01,
-6.94218428912669494046e-01, -6.93936082804800791202e-01,
-6.93653908301078647725e-01, -6.93371908566022487896e-01,
-6.93090077508149882135e-01, -6.92808419565063893231e-01,
-6.92526934253705372946e-01, -6.92245619068708628596e-01,
-6.91964473338724017637e-01, -6.91683502254516024976e-01,
-6.91402702488182807627e-01, -6.91122070984696024176e-01,
-6.90841612116200654015e-01, -6.90561322625015239218e-01,
-6.90281205581785073377e-01, -6.90001257549546886949e-01,
-6.89721478029636569929e-01, -6.89441872453674942101e-01,
-6.89162436357648067187e-01, -6.88883165402184860504e-01,
-6.88604070232913700877e-01, -6.88325140546367397754e-01,
-6.88046384559045987039e-01, -6.87767790884287189002e-01,
-6.87489374500497851805e-01, -6.87211120408326436859e-01,
-6.86933040099159009095e-01, -6.86655124958544749170e-01,
-6.86377381189093749292e-01, -6.86099803770688687621e-01,
-6.85822395405317086770e-01, -6.85545155893080848664e-01,
-6.85268083331586397300e-01, -6.84991179942370131961e-01,
-6.84714444329615257168e-01, -6.84437874267117551952e-01,
-6.84161474467574581837e-01, -6.83885239482271423128e-01,
-6.83609175217499309696e-01, -6.83333274672679680251e-01,
-6.83057543180028203800e-01, -6.82781977587132438146e-01,
-6.82506579583491368446e-01, -6.82231345563520275022e-01,
-6.81956282672124491917e-01, -6.81681382699073523668e-01,
-6.81406648988642449360e-01, -6.81132081961896229672e-01,
-6.80857682178235834591e-01, -6.80583446978993089616e-01,
-6.80309375263567606140e-01, -6.80035474093030112286e-01,
-6.79761733087503428052e-01, -6.79488158765748972989e-01,
-6.79214752196404480955e-01, -6.78941508174092933636e-01,
-6.78668429687879326551e-01, -6.78395515574814367277e-01,
-6.78122767497631007139e-01, -6.77850179968347288373e-01,
-6.77577762100286307145e-01, -6.77305505279880759595e-01,
-6.77033412496333641961e-01, -6.76761485994335831862e-01,
-6.76489719393857269480e-01, -6.76218119206519308051e-01,
-6.75946682529674824913e-01, -6.75675408874354177513e-01,
-6.75404297511148055122e-01, -6.75133351846663343210e-01,
-6.74862564571817591386e-01, -6.74591944752526595508e-01,
-6.74321485785951746372e-01, -6.74051188253726119015e-01,
-6.73781056432154912272e-01, -6.73511083810255595239e-01,
-6.73241275391847304732e-01, -6.72971628848506364662e-01,
-6.72702142902172117722e-01, -6.72432819405576420735e-01,
-6.72163657813787729367e-01, -6.71894658453800697195e-01,
-6.71625820562567810157e-01, -6.71357141277348468122e-01,
-6.71088627224218470246e-01, -6.70820271525421008008e-01,
-6.70552078302100618146e-01, -6.70284043535372409117e-01,
-6.70016173591694408351e-01, -6.69748458199992402484e-01,
-6.69480909726361872458e-01, -6.69213516917172568377e-01,
-6.68946284481173658598e-01, -6.68679216012868060659e-01,
-6.68412303601367385752e-01, -6.68145552943979481597e-01,
-6.67878960338233018668e-01, -6.67612529308768909431e-01,
-6.67346255047431613505e-01, -6.67080142086330152296e-01,
-6.66814188281055542085e-01, -6.66548392089199914778e-01,
-6.66282756236867390598e-01, -6.66017276949984693424e-01,
-6.65751961010806025953e-01, -6.65486796240258193791e-01,
-6.65221796632702977448e-01, -6.64956951917378802364e-01,
-6.64692266831228506518e-01, -6.64427738285177982291e-01,
-6.64163368310645152448e-01, -6.63899157458967215106e-01,
-6.63635101493379009341e-01, -6.63371205633731642060e-01,
-6.63107464413257408076e-01, -6.62843883303304792776e-01,
-6.62580457061119010298e-01, -6.62317190010498935138e-01,
-6.62054075686940191048e-01, -6.61791124448790291090e-01,
-6.61528323678905905147e-01, -6.61265685547834380920e-01,
-6.61003196342271448493e-01, -6.60740870805210378514e-01,
-6.60478697205595710606e-01, -6.60216679784977111822e-01,
-6.59954818896147266116e-01, -6.59693114474321662399e-01,
-6.59431566425846660273e-01, -6.59170169602183664281e-01,
-6.58908933515271577619e-01, -6.58647847617634174533e-01,
-6.58386922235495664069e-01, -6.58126148963177781681e-01,
-6.57865528745428029822e-01, -6.57605066208932775851e-01,
-6.57344758666007500381e-01, -6.57084601064832130035e-01,
-6.56824605124500249254e-01, -6.56564756960135609276e-01,
-6.56305066864535935345e-01, -6.56045529903129254201e-01,
-6.55786144345534061095e-01, -6.55526916459913788771e-01,
-6.55267839667802221015e-01, -6.55008917251094002765e-01,
-6.54750148248612329205e-01, -6.54491533223170662836e-01,
-6.54233070884690626201e-01, -6.53974760242737929161e-01,
-6.53716606549127665637e-01, -6.53458600962904423426e-01,
-6.53200751244333299717e-01, -6.52943051957115550010e-01,
-6.52685505910310381772e-01, -6.52428112891914491200e-01,
-6.52170870940882663191e-01, -6.51913782525463059159e-01,
-6.51656845321644140334e-01, -6.51400060569288341661e-01,
-6.51143425632956684979e-01, -6.50886944226608088471e-01,
-6.50630615305716641927e-01, -6.50374433746492064401e-01,
-6.50118409912749273261e-01, -6.49862529824762003017e-01,
-6.49606805510006379833e-01, -6.49351230777982735276e-01,
-6.49095807187341833355e-01, -6.48840534693980175440e-01,
-6.48585411915660881021e-01, -6.48330438837500522276e-01,
-6.48075616901269135894e-01, -6.47820945942705561649e-01,
-6.47566425177083959674e-01, -6.47312052319633957076e-01,
-6.47057831706227326585e-01, -6.46803759454018356578e-01,
-6.46549835582646559295e-01, -6.46296063896400263538e-01,
-6.46042440334356982135e-01, -6.45788966160048438780e-01,
-6.45535640380269004623e-01, -6.45282465704309915466e-01,
-6.45029437876147415665e-01, -6.44776560034714729674e-01,
-6.44523829468238051987e-01, -6.44271248296943266354e-01,
-6.44018816339636313018e-01, -6.43766532200867991342e-01,
-6.43514396055693715937e-01, -6.43262408599340806958e-01,
-6.43010566875844125079e-01, -6.42758876425902569984e-01,
-6.42507329218555911510e-01, -6.42255935073139161418e-01,
-6.42004685095015736884e-01, -6.41753582691653279291e-01,
-6.41502628715755141009e-01, -6.41251821936975163752e-01,
-6.41001160836058181403e-01, -6.40750647132437567421e-01,
-6.40500281055568221333e-01, -6.40250059968197837712e-01,
-6.39999988601946290245e-01, -6.39750061843456507837e-01,
-6.39500278650730780150e-01, -6.39250648305116686565e-01,
-6.39001157074963743732e-01, -6.38751817077913619514e-01,
-6.38502621514727142227e-01, -6.38253568700912876643e-01,
-6.38004666585740953799e-01, -6.37755907408363187372e-01,
-6.37507291911161622089e-01, -6.37258824885454600029e-01,
-6.37010503187394161451e-01, -6.36762323425182796832e-01,
-6.36514291133987608617e-01, -6.36266404328743595542e-01,
-6.36018659826609211727e-01, -6.35771061168143747366e-01,
-6.35523608549822371927e-01, -6.35276297645185561436e-01,
-6.35029134387725902045e-01, -6.34782110545802358281e-01,
-6.34535236348681808138e-01, -6.34288501462677678511e-01,
-6.34041914641527926122e-01, -6.33795467967775083551e-01,
-6.33549167593703055346e-01, -6.33303008003505141232e-01,
-6.33056993932254119528e-01, -6.32811123131335140357e-01,
-6.32565394272199932324e-01, -6.32319809329721316260e-01,
-6.32074367320891727928e-01, -6.31829070202868159356e-01,
-6.31583911130030539738e-01, -6.31338898763895817190e-01,
-6.31094027655757727757e-01, -6.30849299763053705803e-01,
-6.30604712704740499873e-01, -6.30360268459618455772e-01,
-6.30115967081463446142e-01, -6.29871806376373299940e-01,
-6.29627789478244714871e-01, -6.29383911633328185786e-01,
-6.29140177546854029167e-01, -6.28896584327522600866e-01,
-6.28653133247365936143e-01, -6.28409822109554871972e-01,
-6.28166652841440020794e-01, -6.27923625518381989252e-01,
-6.27680737911588959577e-01, -6.27437993272931704425e-01,
-6.27195386411654398628e-01, -6.26952923663039451974e-01,
-6.26710596052582280535e-01, -6.26468416379213244305e-01,
-6.26226370361392947750e-01, -6.25984468798736148898e-01,
-6.25742705126064335808e-01, -6.25501083628606235898e-01,
-6.25259599318561232195e-01, -6.25018256686031725700e-01,
-6.24777053934279402725e-01, -6.24535988172220113412e-01,
-6.24295067172993101146e-01, -6.24054279498932329417e-01,
-6.23813635187884907296e-01, -6.23573127877870336810e-01,
-6.23332761803093160502e-01, -6.23092531976650820802e-01,
-6.22852442936077554947e-01, -6.22612492694010200012e-01,
-6.22372679074432388902e-01, -6.22133007180836417049e-01,
-6.21893469951140587249e-01, -6.21654073766373604926e-01,
-6.21414816928307800481e-01, -6.21175694260889921239e-01,
-6.20936711402754637490e-01, -6.20697867739223418937e-01,
-6.20459160090374717278e-01, -6.20220590614702582677e-01,
-6.19982159446087810473e-01, -6.19743863890513058124e-01,
-6.19505709002232674010e-01, -6.19267688434115282092e-01,
-6.19029805756627693469e-01, -6.18792058622968155213e-01,
-6.18554452849878200205e-01, -6.18316978693062901939e-01,
-6.18079646961219419943e-01, -6.17842446515595722367e-01,
-6.17605383162825982701e-01, -6.17368461578931437828e-01,
-6.17131668429063418024e-01, -6.16895018848982901183e-01,
-6.16658499158108108773e-01, -6.16422121003326939359e-01,
-6.16185873829411923097e-01, -6.15949765858643694116e-01,
-6.15713791520932085533e-01, -6.15477953698487789680e-01,
-6.15242252020492652598e-01, -6.15006685088008708817e-01,
-6.14771253279671636705e-01, -6.14535956479875133951e-01,
-6.14300794772409064493e-01, -6.14065767937721718184e-01,
-6.13830876770228073269e-01, -6.13596118311820704072e-01,
-6.13361498012579442474e-01, -6.13127008206162837922e-01,
-6.12892657344050406643e-01, -6.12658436050471988388e-01,
-6.12424351025287472261e-01, -6.12190401608632028818e-01,
-6.11956583740106974112e-01, -6.11722903145300644923e-01,
-6.11489352158128496306e-01, -6.11255938953534583291e-01,
-6.11022655261633462764e-01, -6.10789509223216509071e-01,
-6.10556493308809900000e-01, -6.10323612731711540036e-01,
-6.10090865344073973731e-01, -6.09858248936054225808e-01,
-6.09625768906936205127e-01, -6.09393417045297591805e-01,
-6.09161204033737857522e-01, -6.08929117705023448259e-01,
-6.08697168105810870742e-01, -6.08465349568450442064e-01,
-6.08233663541013047649e-01, -6.08002109898864828708e-01,
-6.07770687692471445196e-01, -6.07539400844602006657e-01,
-6.07308240201651194923e-01, -6.07077216103529160307e-01,
-6.06846324283877858186e-01, -6.06615560292348421356e-01,
-6.06384929432888464262e-01, -6.06154431703861962255e-01,
-6.05924061807866065621e-01, -6.05693829760275859186e-01,
-6.05463723148737864577e-01, -6.05233748079676781018e-01,
-6.05003903715618296388e-01, -6.04774198475906521466e-01,
-6.04544610696509998604e-01, -6.04315162734855082505e-01,
-6.04085842704623399158e-01, -6.03856653441919410952e-01,
-6.03627595488644308475e-01, -6.03398663841088644944e-01,
-6.03169866796318343560e-01, -6.02941198521520616005e-01,
-6.02712662875009685948e-01, -6.02484250256341447027e-01,
-6.02255972857237198426e-01, -6.02027825038867536733e-01,
-6.01799805988958325109e-01, -6.01571913419564285874e-01,
-6.01344157294740888631e-01, -6.01116522397953101375e-01,
-6.00889026103673673518e-01, -6.00661647658158770469e-01,
-6.00434407998426733499e-01, -6.00207288833633056946e-01,
-5.99980308862523514790e-01, -5.99753445108572424971e-01,
-5.99526726075654492476e-01, -5.99300116604148724875e-01,
-5.99073650597569562493e-01, -5.98847305832576282114e-01,
-5.98621092595534198821e-01, -5.98395003140193559865e-01,
-5.98169046989315500440e-01, -5.97943216149849243735e-01,
-5.97717510719493860805e-01, -5.97491938300504732418e-01,
-5.97266490737901722952e-01, -5.97041170697608758466e-01,
-5.96815975670910492390e-01, -5.96590913026744495973e-01,
-5.96365978149817177467e-01, -5.96141159780623763886e-01,
-5.95916485220735703265e-01, -5.95691923578596127520e-01,
-5.95467492887766125520e-01, -5.95243196609040237099e-01,
-5.95019014041551219663e-01, -5.94794968648619137852e-01,
-5.94571043157184897510e-01, -5.94347249668552901625e-01,
-5.94123579402305201924e-01, -5.93900033027068730007e-01,
-5.93676616648752819572e-01, -5.93453327526834439887e-01,
-5.93230159341627150127e-01, -5.93007117760657065375e-01,
-5.92784208785247512807e-01, -5.92561413918450186067e-01,
-5.92338756443251623907e-01, -5.92116217604009120734e-01,
-5.91893804436822379422e-01, -5.91671518728806522525e-01,
-5.91449357471272030295e-01, -5.91227319735991518890e-01,
-5.91005412244563821389e-01, -5.90783620214691107542e-01,
-5.90561962526354289338e-01, -5.90340423145411241634e-01,
-5.90119013800835201522e-01, -5.89897725962619245976e-01,
-5.89676559670074262876e-01, -5.89455523295964733954e-01,
-5.89234605661662969034e-01, -5.89013820757174455522e-01,
-5.88793146152845503494e-01, -5.88572612873802136768e-01,
-5.88352186304420876617e-01, -5.88131895650970792921e-01,
-5.87911725759226233556e-01, -5.87691674512207162806e-01,
-5.87471754356189146407e-01, -5.87251951150662199197e-01,
-5.87032275483777565839e-01, -5.86812721495183042819e-01,
-5.86593290862264971075e-01, -5.86373982735830190371e-01,
-5.86154798835264334578e-01, -5.85935733132218805608e-01,
-5.85716796844832021662e-01, -5.85497984656510039869e-01,
-5.85279284263748866834e-01, -5.85060716669546732049e-01,
-5.84842266044768188671e-01, -5.84623941175344330468e-01,
-5.84405733922557346638e-01, -5.84187656879476824301e-01,
-5.83969690164282795308e-01, -5.83751856007703295859e-01,
-5.83534141248000293167e-01, -5.83316542773784973974e-01,
-5.83099075016479395650e-01, -5.82881716889396495063e-01,
-5.82664493604380329117e-01, -5.82447381280095655143e-01,
-5.82230394350684243854e-01, -5.82013532488527274289e-01,
-5.81796782569958814690e-01, -5.81580163889648171782e-01,
-5.81363657096067520946e-01, -5.81147275597175272388e-01,
-5.80931018640279073217e-01, -5.80714875828189036611e-01,
-5.80498855974745042730e-01, -5.80282956573518804433e-01,
-5.80067178836383479101e-01, -5.79851520422275057420e-01,
-5.79635978307705301837e-01, -5.79420566927691282899e-01,
-5.79205265093265642129e-01, -5.78990087245926599024e-01,
-5.78775030336261320230e-01, -5.78560092120421365358e-01,
-5.78345273447344543349e-01, -5.78130573165126393498e-01,
-5.77915995032448615021e-01, -5.77701536342358656917e-01,
-5.77487192988114461656e-01, -5.77272972927765581908e-01,
-5.77058870787597544272e-01, -5.76844888928548904516e-01,
-5.76631023280578580703e-01, -5.76417276587042004543e-01,
-5.76203653120429537537e-01, -5.75990144223295308379e-01,
-5.75776757901189761846e-01, -5.75563481965228884718e-01,
-5.75350334813656383304e-01, -5.75137299745865471223e-01,
-5.74924380462553563653e-01, -5.74711590037412012322e-01,
-5.74498906002588793918e-01, -5.74286349276446173029e-01,
-5.74073903356870807180e-01, -5.73861579806341892684e-01,
-5.73649371228796445266e-01, -5.73437284470137975667e-01,
-5.73225310718684766265e-01, -5.73013456023520051374e-01,
-5.72801716175861619362e-01, -5.72590101961756081650e-01,
-5.72378596797541217001e-01, -5.72167211528335384330e-01,
-5.71955941709068382828e-01, -5.71744794274904322151e-01,
-5.71533757106126860670e-01, -5.71322838218824013978e-01,
-5.71112040020102962323e-01, -5.70901356041317420420e-01,
-5.70690787398203669412e-01, -5.70480336096462870010e-01,
-5.70270004173424105431e-01, -5.70059781474071325391e-01,
-5.69849684229397412949e-01, -5.69639691198059239241e-01,
-5.69429826410952522053e-01, -5.69220070865192440124e-01,
-5.69010431837938868149e-01, -5.68800910399309023191e-01,
-5.68591506167543392358e-01, -5.68382208423693136012e-01,
-5.68173038073570446649e-01, -5.67963978092230536987e-01,
-5.67755030970157004155e-01, -5.67546203770359025675e-01,
-5.67337488102058862260e-01, -5.67128888113616835831e-01,
-5.66920406778240515422e-01, -5.66712039230608977114e-01,
-5.66503779607057222911e-01, -5.66295645051695717420e-01,
-5.66087617555229849486e-01, -5.65879707307245127801e-01,
-5.65671913910436696682e-01, -5.65464228764436582786e-01,
-5.65256664316280965643e-01, -5.65049212905805120499e-01,
-5.64841870374890531181e-01, -5.64634649840305424817e-01,
-5.64427536520706540912e-01, -5.64220542897088006562e-01,
-5.64013656178556255227e-01, -5.63806892695951078487e-01,
-5.63600233444419784767e-01, -5.63393693409048657017e-01,
-5.63187265181959162419e-01, -5.62980952233706921639e-01,
-5.62774748089948873009e-01, -5.62568664001630525107e-01,
-5.62362683791054585036e-01, -5.62156827390452251691e-01,
-5.61951075952079159848e-01, -5.61745440231198656100e-01,
-5.61539918406243399041e-01, -5.61334507008219185664e-01,
-5.61129210558799051967e-01, -5.60924025616156063379e-01,
-5.60718950250054470885e-01, -5.60513995623263650003e-01,
-5.60309141366683527430e-01, -5.60104413090462549540e-01,
-5.59899784602460259819e-01, -5.59695279181735561025e-01,
-5.59490874607678101427e-01, -5.59286591780185582401e-01,
-5.59082414023761575805e-01, -5.58878353612881406676e-01,
-5.58674400476881993782e-01, -5.58470560272198546237e-01,
-5.58266831619624648297e-01, -5.58063214379549865640e-01,
-5.57859710489623239482e-01, -5.57656312338858040079e-01,
-5.57453037257682026961e-01, -5.57249857062983466882e-01,
-5.57046800101556049967e-01, -5.56843848224561788207e-01,
-5.56641012152947034508e-01, -5.56438278327634150422e-01,
-5.56235667912246767308e-01, -5.56033154514851135630e-01,
-5.55830766660204256269e-01, -5.55628472520565130921e-01,
-5.55426303826917155959e-01, -5.55224232538292339356e-01,
-5.55022283208224775919e-01, -5.54820430367028993857e-01,
-5.54618706636430314205e-01, -5.54417074054438074882e-01,
-5.54215562440321773963e-01, -5.54014157534220008650e-01,
-5.53812864204566768223e-01, -5.53611677237488386538e-01,
-5.53410601444173755326e-01, -5.53209633969611869198e-01,
-5.53008781422658302063e-01, -5.52808031398771770881e-01,
-5.52607393379650480014e-01, -5.52406864194784130717e-01,
-5.52206447044515491562e-01, -5.52006132297983898027e-01,
-5.51805932926547226813e-01, -5.51605840203247654863e-01,
-5.51405853712816806933e-01, -5.51205983843285340917e-01,
-5.51006211809542234548e-01, -5.50806557660515672126e-01,
-5.50607004689088852523e-01, -5.50407566147187443661e-01,
-5.50208228085966921661e-01, -5.50009010697139366641e-01,
-5.49809891866183120257e-01, -5.49610883980118702929e-01,
-5.49411981957127704135e-01, -5.49213193737463911681e-01,
-5.49014503817799592866e-01, -5.48815932743580869868e-01,
-5.48617458539834013109e-01, -5.48419103857524015133e-01,
-5.48220844771248438931e-01, -5.48022698452298229199e-01,
-5.47824664844393738328e-01, -5.47626727001364610459e-01,
-5.47428908060687779980e-01, -5.47231188297979453949e-01,
-5.47033578769815509446e-01, -5.46836077326017133693e-01,
-5.46638681510724033785e-01, -5.46441392121685520777e-01,
-5.46244208423764421312e-01, -5.46047132559760117765e-01,
-5.45850167869482705285e-01, -5.45653298850893309080e-01,
-5.45456550644724424970e-01, -5.45259894069439088327e-01,
-5.45063353655226401351e-01, -5.44866916342223062131e-01,
-5.44670587487950941252e-01, -5.44474358722185636239e-01,
-5.44278246992432546136e-01, -5.44082226406505276017e-01,
-5.43886327706291639039e-01, -5.43690520871651483681e-01,
-5.43494828186031564421e-01, -5.43299235239269484588e-01,
-5.43103755036826063574e-01, -5.42908372318762322273e-01,
-5.42713101591759894404e-01, -5.42517933616644687511e-01,
-5.42322868491689424886e-01, -5.42127915062977416838e-01,
-5.41933060199644156540e-01, -5.41738314051451785858e-01,
-5.41543671501958590042e-01, -5.41349131691297391633e-01,
-5.41154703175379503399e-01, -5.40960374942168753520e-01,
-5.40766148956284276039e-01, -5.40572028371287816029e-01,
-5.40378020960053717658e-01, -5.40184103653394309674e-01,
-5.39990305075831233950e-01, -5.39796600853690300426e-01,
-5.39603003977793482804e-01, -5.39409509210268311996e-01,
-5.39216124511781913498e-01, -5.39022834453409704913e-01,
-5.38829659262570759282e-01, -5.38636578161997059411e-01,
-5.38443609329856687218e-01, -5.38250734358359017584e-01,
-5.38057975172885782911e-01, -5.37865307183183372075e-01,
-5.37672750945531352507e-01, -5.37480293528547869997e-01,
-5.37287943749739205224e-01, -5.37095690446331985868e-01,
-5.36903547100173295092e-01, -5.36711504474260636677e-01,
-5.36519563683013567257e-01, -5.36327729505757688777e-01,
-5.36135992886641155053e-01, -5.35944362918005068330e-01,
-5.35752834638077879426e-01, -5.35561407625734231530e-01,
-5.35370088527245657772e-01, -5.35178862354523610101e-01,
-5.34987748886039060636e-01, -5.34796728699478363112e-01,
-5.34605815002141993020e-01, -5.34415007914754935925e-01,
-5.34224293747115996922e-01, -5.34033693611692839021e-01,
-5.33843181452299697654e-01, -5.33652784501857047061e-01,
-5.33462475764223453822e-01, -5.33272280111689811477e-01,
-5.33082180930588456214e-01, -5.32892186275686574604e-01,
-5.32702291717452758313e-01, -5.32512495743376668145e-01,
-5.32322808833029625930e-01, -5.32133212932378696358e-01,
-5.31943725074500606276e-01, -5.31754339884605298217e-01,
-5.31565050652905601858e-01, -5.31375867241598021096e-01,
-5.31186779263425279396e-01, -5.30997796053478632317e-01,
-5.30808913010392569021e-01, -5.30620128028665871689e-01,
-5.30431454131669366525e-01, -5.30242863683162979349e-01,
-5.30054387149510808364e-01, -5.29866008532592913660e-01,
-5.29677727830911937446e-01, -5.29489549872706133371e-01,
-5.29301466522391517167e-01, -5.29113494318193988697e-01,
-5.28925608770407507109e-01, -5.28737835420275414933e-01,
-5.28550152471884304717e-01, -5.28362576864161215262e-01,
-5.28175096164924973152e-01, -5.27987720812230887368e-01,
-5.27800432661909901810e-01, -5.27613260324969468584e-01,
-5.27426174556774984836e-01, -5.27239196669631482450e-01,
-5.27052315362437129309e-01, -5.26865532175552986338e-01,
-5.26678852248636530931e-01, -5.26492264658567798996e-01,
-5.26305785606426601575e-01, -5.26119394738626899866e-01,
-5.25933112564948679335e-01, -5.25746922103342950727e-01,
-5.25560837244612333308e-01, -5.25374841759336907998e-01,
-5.25188953146781378756e-01, -5.25003162342790208328e-01,
-5.24817465752979828153e-01, -5.24631875643167933099e-01,
-5.24446368896209325072e-01, -5.24260981011384075146e-01,
-5.24075671339813808913e-01, -5.23890477570763124504e-01,
-5.23705367827149603777e-01, -5.23520364872812615786e-01,
-5.23335454232961572174e-01, -5.23150648691175557126e-01,
-5.22965933939672056319e-01, -5.22781320898389578744e-01,
-5.22596802547097949443e-01, -5.22412384870908130807e-01,
-5.22228062125477787703e-01, -5.22043840127194180845e-01,
-5.21859712530721830959e-01, -5.21675687725144388018e-01,
-5.21491749675332627589e-01, -5.21307920605108998657e-01,
-5.21124183533665741308e-01, -5.20940539456928863871e-01,
-5.20757001372001870898e-01, -5.20573549822157310984e-01,
-5.20390204933718125702e-01, -5.20206950361603026600e-01,
-5.20023797832201872815e-01, -5.19840739136778307028e-01,
-5.19657773032146108605e-01, -5.19474912699786184334e-01,
-5.19292140184574591011e-01, -5.19109469422041946984e-01,
-5.18926896152802741291e-01, -5.18744412302997615072e-01,
-5.18562032075707168843e-01, -5.18379740260081822711e-01,
-5.18197549968825610378e-01, -5.18015457489585662287e-01,
-5.17833453383197195308e-01, -5.17651556766932641196e-01,
-5.17469745314348417153e-01, -5.17288033334592833867e-01,
-5.17106419445129028567e-01, -5.16924894866955919603e-01,
-5.16743473746873793750e-01, -5.16562141804293717406e-01,
-5.16380908487159562270e-01, -5.16199772636025677741e-01,
-5.16018729440732126790e-01, -5.15837776949621074074e-01,
-5.15656927779485463326e-01, -5.15476166942422153738e-01,
-5.15295508245639188871e-01, -5.15114933799949437088e-01,
-5.14934467827279918062e-01, -5.14754087208464383707e-01,
-5.14573804318886995901e-01, -5.14393615127918146790e-01,
-5.14213523382693216135e-01, -5.14033518125299626611e-01,
-5.13853617088510961075e-01, -5.13673805002628713900e-01,
-5.13494091686059750401e-01, -5.13314464310747786691e-01,
-5.13134942018768192007e-01, -5.12955505773359687893e-01,
-5.12776167876007660240e-01, -5.12596920509274522892e-01,
-5.12417771465554672261e-01, -5.12238708568578005043e-01,
-5.12059750379289191358e-01, -5.11880879533663235570e-01,
-5.11702102223372312650e-01, -5.11523422221623169648e-01,
-5.11344829419787094693e-01, -5.11166338127431063576e-01,
-5.10987934742527905030e-01, -5.10809625836007308308e-01,
-5.10631409902048583049e-01, -5.10453286393003913268e-01,
-5.10275259005286696556e-01, -5.10097324676761276763e-01,
-5.09919480783686318581e-01, -5.09741729707290813778e-01,
-5.09564075722271581093e-01, -5.09386510524484137363e-01,
-5.09209040704066917549e-01, -5.09031659380481893429e-01,
-5.08854376309871736517e-01, -5.08677181699944691573e-01,
-5.08500082611985537717e-01, -5.08323071769016254784e-01,
-5.08146160041792915862e-01, -5.07969333576011261577e-01,
-5.07792603390520680406e-01, -5.07615961615968891429e-01,
-5.07439417535044401397e-01, -5.07262964238087699087e-01,
-5.07086597729305976756e-01, -5.06910329725660746547e-01,
-5.06734150882708900276e-01, -5.06558064509521788210e-01,
-5.06382066714256118267e-01, -5.06206169755213153394e-01,
-5.06030350842774145903e-01, -5.05854632997757347468e-01,
-5.05679002805864419301e-01, -5.05503468551726342639e-01,
-5.05328021686990758177e-01, -5.05152665768693220905e-01,
-5.04977406292914432484e-01, -5.04802228894167148709e-01,
-5.04627152010708512897e-01, -5.04452160958478557085e-01,
-5.04277262507847989781e-01, -5.04102455437264618254e-01,
-5.03927737862568170257e-01, -5.03753107366079477814e-01,
-5.03578575502675152009e-01, -5.03404131998141490811e-01,
-5.03229772866844449197e-01, -5.03055513149661570615e-01,
-5.02881341372201307038e-01, -5.02707254863539287904e-01,
-5.02533264605894314236e-01, -5.02359362868927239454e-01,
-5.02185547240035057293e-01, -5.02011835099967607121e-01,
-5.01838192865942445131e-01, -5.01664659257242795398e-01,
-5.01491202386485701581e-01, -5.01317844028692949365e-01,
-5.01144573674645599226e-01, -5.00971389234455277695e-01,
-5.00798298401023855853e-01, -5.00625294844373347480e-01,
-5.00452385015643708144e-01, -5.00279560616122997985e-01,
-5.00106826037778007255e-01, -4.99934183187324188147e-01,
-4.99761631221804392133e-01, -4.99589160430459866546e-01,
-4.99416788147540702258e-01, -4.99244499450290479814e-01,
-4.99072303167870379159e-01, -4.98900190082264438640e-01,
-4.98728177060504151985e-01, -4.98556239380091414937e-01,
-4.98384403184633395512e-01, -4.98212644501553447718e-01,
-4.98040988374067628008e-01, -4.97869403305372104640e-01,
-4.97697923184240553773e-01, -4.97526522183478925321e-01,
-4.97355213843734156320e-01, -4.97183992181355394191e-01,
-4.97012856414427717233e-01, -4.96841815654261997892e-01,
-4.96670856589271125792e-01, -4.96499989826879928323e-01,
-4.96329208600718163602e-01, -4.96158518192971298433e-01,
-4.95987915417138214291e-01, -4.95817396561167578195e-01,
-4.95646968483893668456e-01, -4.95476629813774605005e-01,
-4.95306379178141298336e-01, -4.95136212263342589956e-01,
-4.94966136520781141428e-01, -4.94796148810238756166e-01,
-4.94626243065314996628e-01, -4.94456435515959080718e-01,
-4.94286700836386871938e-01, -4.94117068220431165937e-01,
-4.93947513273770733022e-01, -4.93778048500503219387e-01,
-4.93608670630300450100e-01, -4.93439380240378033804e-01,
-4.93270178292201766368e-01, -4.93101060362692411587e-01,
-4.92932032006830334048e-01, -4.92763086603644373529e-01,
-4.92594233906167910941e-01, -4.92425463874980429146e-01,
-4.92256784562988658482e-01, -4.92088184973856646032e-01,
-4.91919678688281070134e-01, -4.91751255907422357705e-01,
-4.91582919894200887079e-01, -4.91414667395775106584e-01,
-4.91246508160590455994e-01, -4.91078428799448130082e-01,
-4.90910439593086167509e-01, -4.90742535159492621055e-01,
-4.90574715570106012485e-01, -4.90406985921184590538e-01,
-4.90239336932127289792e-01, -4.90071778277338720997e-01,
-4.89904302891543297349e-01, -4.89736918185567804418e-01,
-4.89569612757251415580e-01, -4.89402391276797965602e-01,
-4.89235268817294621790e-01, -4.89068213943802065913e-01,
-4.88901259091894080377e-01, -4.88734384185310899440e-01,
-4.88567592390033778038e-01, -4.88400891118397850743e-01,
-4.88234269906823503682e-01, -4.88067740845552044959e-01,
-4.87901288388939091689e-01, -4.87734929101708958310e-01,
-4.87568645798221456111e-01, -4.87402457128699562183e-01,
-4.87236350381375693530e-01, -4.87070324225484241332e-01,
-4.86904385519984495012e-01, -4.86738530511547085045e-01,
-4.86572767354529089889e-01, -4.86407078360703515330e-01,
-4.86241481425138122319e-01, -4.86075967359270388890e-01,
-4.85910532670543182654e-01, -4.85745189341874772371e-01,
-4.85579926461763289325e-01, -4.85414753341555094135e-01,
-4.85249654823238341095e-01, -4.85084648699901588298e-01,
-4.84919723660684809374e-01, -4.84754884804198205028e-01,
-4.84590123046861998013e-01, -4.84425458448513146514e-01,
-4.84260864556867121067e-01, -4.84096360065999875566e-01,
-4.83931941355376094016e-01, -4.83767604213061086504e-01,
-4.83603346755586915862e-01, -4.83439180728759743122e-01,
-4.83275094560436269120e-01, -4.83111089265769844125e-01,
-4.82947172356291476447e-01, -4.82783335122464629663e-01,
-4.82619582539163261004e-01, -4.82455914592298529264e-01,
-4.82292326363351897545e-01, -4.82128826364616291933e-01,
-4.81965407817179114502e-01, -4.81802066972656928279e-01,
-4.81638814427624573078e-01, -4.81475645071778979300e-01,
-4.81312557573886912188e-01, -4.81149551193313373965e-01,
-4.80986630223831979070e-01, -4.80823789406853552286e-01,
-4.80661034307090506701e-01, -4.80498359100152816481e-01,
-4.80335770343018442219e-01, -4.80173258808035297029e-01,
-4.80010832497092865268e-01, -4.79848490982026310014e-01,
-4.79686227973605716635e-01, -4.79524046705174122884e-01,
-4.79361951708459965715e-01, -4.79199932799077243928e-01,
-4.79038003831099401530e-01, -4.78876153100232238025e-01,
-4.78714380041965981150e-01, -4.78552698618633920447e-01,
-4.78391087073025467191e-01, -4.78229573768165938663e-01,
-4.78068122888519353442e-01, -4.77906771102107552629e-01,
-4.77745485783475642982e-01, -4.77584293711196150589e-01,
-4.77423176275788341272e-01, -4.77262147608990328074e-01,
-4.77101192145071517636e-01, -4.76940324487603428683e-01,
-4.76779535315644098503e-01, -4.76618824957646625151e-01,
-4.76458201420741689347e-01, -4.76297654699695649505e-01,
-4.76137194456570100876e-01, -4.75976803224222311250e-01,
-4.75816507681549927256e-01, -4.75656285635331022021e-01,
-4.75496143300199403114e-01, -4.75336089186713772747e-01,
-4.75176105389747416297e-01, -4.75016210315764575434e-01,
-4.74856392947519134751e-01, -4.74696656595788579747e-01,
-4.74536999034709916501e-01, -4.74377425856956969064e-01,
-4.74217928093568941161e-01, -4.74058513675973014490e-01,
-4.73899182199162827267e-01, -4.73739927351737866168e-01,
-4.73580752432562757104e-01, -4.73421661733451903942e-01,
-4.73262645964154682332e-01, -4.73103715642114674989e-01,
-4.72944860339552519690e-01, -4.72786088898399126101e-01,
-4.72627398730451619979e-01, -4.72468780170721247558e-01,
-4.72310252115622830615e-01, -4.72151793347969528369e-01,
-4.71993425136610800230e-01, -4.71835128326818731281e-01,
-4.71676913565172273302e-01, -4.71518779771825324865e-01,
-4.71360720619582784785e-01, -4.71202751321201207535e-01,
-4.71044850880461440923e-01, -4.70887032190129728448e-01,
-4.70729298202972046283e-01, -4.70571635391029530204e-01,
-4.70414061385758586198e-01, -4.70256552716906972567e-01,
-4.70099140930541448125e-01, -4.69941790367873535317e-01,
-4.69784533886893507226e-01, -4.69627342769655231614e-01,
-4.69470243150597432713e-01, -4.69313215089266821956e-01,
-4.69156267509552749040e-01, -4.68999395832224053038e-01,
-4.68842609450314307118e-01, -4.68685897722662947462e-01,
-4.68529260293265359394e-01, -4.68372709227301453616e-01,
-4.68216230147668388550e-01, -4.68059834969985155695e-01,
-4.67903512760620088340e-01, -4.67747272986739126566e-01,
-4.67591111065052189577e-01, -4.67435024685682654066e-01,
-4.67279016495556198674e-01, -4.67123089392717960600e-01,
-4.66967240313931553075e-01, -4.66811467438227656324e-01,
-4.66655769936848929813e-01, -4.66500152945792889714e-01,
-4.66344619101570212472e-01, -4.66189152722139621421e-01,
-4.66033769195671743191e-01, -4.65878467355010317252e-01,
-4.65723236480608038246e-01, -4.65568087090199089761e-01,
-4.65413010184134667835e-01, -4.65258020067406741216e-01,
-4.65103102047306760092e-01, -4.64948255886194261599e-01,
-4.64793497227340202116e-01, -4.64638808438783912358e-01,
-4.64484199701613809097e-01, -4.64329670275179240413e-01,
-4.64175212940993731081e-01, -4.64020834961912320704e-01,
-4.63866536856742783801e-01, -4.63712309287399704338e-01,
-4.63558166735674515024e-01, -4.63404094140099642729e-01,
-4.63250103737141538662e-01, -4.63096183994143872908e-01,
-4.62942346453523445593e-01, -4.62788578830010732812e-01,
-4.62634896370526571552e-01, -4.62481283900268602682e-01,
-4.62327753343912351003e-01, -4.62174294529301699086e-01,
-4.62020913868642191247e-01, -4.61867607061139495706e-01,
-4.61714384897765395266e-01, -4.61561230867168159619e-01,
-4.61408155520300011787e-01, -4.61255155516445081165e-01,
-4.61102233667515015725e-01, -4.60949382066578872141e-01,
-4.60796618353578379956e-01, -4.60643913403289584352e-01,
-4.60491299021441868877e-01, -4.60338755341436867141e-01,
-4.60186285320456245351e-01, -4.60033896996370872401e-01,
-4.59881577612257952392e-01, -4.59729336630324780799e-01,
-4.59577171310406873417e-01, -4.59425083150955204658e-01,
-4.59273068898329361875e-01, -4.59121128892770402619e-01,
-4.58969265026953621156e-01, -4.58817480565808177850e-01,
-4.58665760556941526360e-01, -4.58514128017382727176e-01,
-4.58362561710762062006e-01, -4.58211078862046317095e-01,
-4.58059665335349530668e-01, -4.57908326921637853779e-01,
-4.57757065768802040573e-01, -4.57605878670184207380e-01,
-4.57454765128654905482e-01, -4.57303730339389313819e-01,
-4.57152765194686672157e-01, -4.57001878578433717859e-01,
-4.56851066414525497361e-01, -4.56700324947624303196e-01,
-4.56549662099315856079e-01, -4.56399072290335383606e-01,
-4.56248558740286580537e-01, -4.56098114150018663082e-01,
-4.55947753320660786880e-01, -4.55797457874459521765e-01,
-4.55647241817815684684e-01, -4.55497101030491791107e-01,
-4.55347026811166788463e-01, -4.55197035733620636311e-01,
-4.55047114907537797457e-01, -4.54897265792787275362e-01,
-4.54747495440209426043e-01, -4.54597796538315446213e-01,
-4.54448168930477292005e-01, -4.54298620554697607510e-01,
-4.54149142167335262421e-01, -4.53999740453209232882e-01,
-4.53850409092556528190e-01, -4.53701155503739850250e-01,
-4.53551967508941333840e-01, -4.53402864049327503082e-01,
-4.53253826241534985009e-01, -4.53104865974366610715e-01,
-4.52955976927715830982e-01, -4.52807161317335338246e-01,
-4.52658416600321633627e-01, -4.52509750732534687945e-01,
-4.52361156785181017792e-01, -4.52212632165832073561e-01,
-4.52064182997125807439e-01, -4.51915809732679141231e-01,
-4.51767504435387212691e-01, -4.51619276048310869243e-01,
-4.51471119088053707280e-01, -4.51323035369269209838e-01,
-4.51175023116738904694e-01, -4.51027087616684640992e-01,
-4.50879220675307723631e-01, -4.50731427429839681675e-01,
-4.50583706701023323227e-01, -4.50436058068656608455e-01,
-4.50288484392804111422e-01, -4.50140985829281470298e-01,
-4.49993547718889774778e-01, -4.49846195014996619310e-01,
-4.49698909618556408319e-01, -4.49551694268899182383e-01,
-4.49404556107751540495e-01, -4.49257486180618614835e-01,
-4.49110490812010820783e-01, -4.48963564834253037183e-01,
-4.48816711417663771755e-01, -4.48669934224515287724e-01,
-4.48523226611271530473e-01, -4.48376589138061998341e-01,
-4.48230026207904586055e-01, -4.48083530824469000731e-01,
-4.47937115394188400952e-01, -4.47790759639401680925e-01,
-4.47644487560837300855e-01, -4.47498279312596392021e-01,
-4.47352145574061499378e-01, -4.47206085825344268336e-01,
-4.47060091466615849853e-01, -4.46914175065337260229e-01,
-4.46768328479106580087e-01, -4.46622549358328568836e-01,
-4.46476844067914602210e-01, -4.46331211849556985793e-01,
-4.46185649371574566402e-01, -4.46040159543129255404e-01,
-4.45894734059254282954e-01, -4.45749392054783755146e-01,
-4.45604109998832320638e-01, -4.45458907000752302174e-01,
-4.45313763681632224234e-01, -4.45168704920153035509e-01,
-4.45023706459857115725e-01, -4.44878784568539797917e-01,
-4.44733931959089667796e-01, -4.44589150336285765519e-01,
-4.44444440168124510482e-01, -4.44299797877839797167e-01,
-4.44155226128629454507e-01, -4.44010729020339223183e-01,
-4.43866298666259206929e-01, -4.43721940161641459355e-01,
-4.43577652188057836025e-01, -4.43433434923970193342e-01,
-4.43289288973958195417e-01, -4.43145211741241440428e-01,
-4.43001201832491808830e-01, -4.42857267417801292453e-01,
-4.42713399561871723265e-01, -4.42569603484062712440e-01,
-4.42425878418105156253e-01, -4.42282222209714359629e-01,
-4.42138633066428476948e-01, -4.41995120312379197181e-01,
-4.41851670795243789414e-01, -4.41708294272568247063e-01,
-4.41564987218233395705e-01, -4.41421753979170328197e-01,
-4.41278580693772737309e-01, -4.41135484933924015838e-01,
-4.40992454977177983366e-01, -4.40849497789696342931e-01,
-4.40706608405147748364e-01, -4.40563788546826096137e-01,
-4.40421036287886535909e-01, -4.40278357612415072175e-01,
-4.40135741686783155124e-01, -4.39993203509676911178e-01,
-4.39850727447593570218e-01, -4.39708327508245289117e-01,
-4.39565985646027390654e-01, -4.39423726508034517835e-01,
-4.39281525430847197278e-01, -4.39139400541693647462e-01,
-4.38997337522693764633e-01, -4.38855353166397843534e-01,
-4.38713428148096995507e-01, -4.38571578270592898896e-01,
-4.38429793175001303318e-01, -4.38288076142315019545e-01,
-4.38146435583318394347e-01, -4.38004856925622299002e-01,
-4.37863345344516097235e-01, -4.37721905887101636612e-01,
-4.37580535541424453516e-01, -4.37439230132329770484e-01,
-4.37297998196520043557e-01, -4.37156832114081794760e-01,
-4.37015731476225077756e-01, -4.36874705538022933826e-01,
-4.36733740039714768422e-01, -4.36592849237657620876e-01,
-4.36452023893796947629e-01, -4.36311264352250760545e-01,
-4.36170578474602832486e-01, -4.36029956822141295802e-01,
-4.35889406936388223990e-01, -4.35748919265838252635e-01,
-4.35608502123248308990e-01, -4.35468154160838893940e-01,
-4.35327872456970021986e-01, -4.35187658870110516407e-01,
-4.35047508888025347140e-01, -4.34907438701185977692e-01,
-4.34767421587553992701e-01, -4.34627481189585829213e-01,
-4.34487605538849241960e-01, -4.34347796514875039708e-01,
-4.34208058567971622033e-01, -4.34068383193245921348e-01,
-4.33928777608219518047e-01, -4.33789243799441504024e-01,
-4.33649766603194375403e-01, -4.33510371160185314920e-01,
-4.33371027950657794481e-01, -4.33231762857705704484e-01,
-4.33092557748064654888e-01, -4.32953425744085129701e-01,
-4.32814354841371762284e-01, -4.32675357583413688900e-01,
-4.32536418152391188841e-01, -4.32397553748481100477e-01,
-4.32258756092280593819e-01, -4.32120018749481138443e-01,
-4.31981353384978172816e-01, -4.31842753301111881292e-01,
-4.31704222447754082381e-01, -4.31565751723078538937e-01,
-4.31427351232775313505e-01, -4.31289023183523967386e-01,
-4.31150748642916026299e-01, -4.31012556430421800435e-01,
-4.30874417255794339709e-01, -4.30736352405325817472e-01,
-4.30598350727577461328e-01, -4.30460413190271118378e-01,
-4.30322547073958339148e-01, -4.30184744640451977027e-01,
-4.30047007210207721251e-01, -4.29909337239590294555e-01,
-4.29771734758555123967e-01, -4.29634197190916888864e-01,
-4.29496723635589494616e-01, -4.29359320273103528542e-01,
-4.29221974458292798715e-01, -4.29084708239550083331e-01,
-4.28947490771954986766e-01, -4.28810356331569053623e-01,
-4.28673276890164822728e-01, -4.28536263229363001415e-01,
-4.28399322602652121716e-01, -4.28262437566197862182e-01,
-4.28125625938365672596e-01, -4.27988878593011767837e-01,
-4.27852191864603992322e-01, -4.27715578365543303008e-01,
-4.27579024839372157096e-01, -4.27442538171905417332e-01,
-4.27306115252213791766e-01, -4.27169761638197587050e-01,
-4.27033469385057595780e-01, -4.26897242362347606459e-01,
-4.26761084212522345815e-01, -4.26624987672080846490e-01,
-4.26488955800829794285e-01, -4.26352994798914308738e-01,
-4.26217087981818953946e-01, -4.26081262359846446586e-01,
-4.25945482455656998511e-01, -4.25809784937209889755e-01,
-4.25674136841104333584e-01, -4.25538566297759102142e-01,
-4.25403049628253704384e-01, -4.25267608714368750000e-01,
-4.25132224411385206686e-01, -4.24996906712915012427e-01,
-4.24861657140971293867e-01, -4.24726470789760501834e-01,
-4.24591343408701860085e-01, -4.24456285730042126580e-01,
-4.24321292602986122056e-01, -4.24186362722597742891e-01,
-4.24051495283545076820e-01, -4.23916694812093208800e-01,
-4.23781955184383107849e-01, -4.23647285193715694707e-01,
-4.23512678142488330213e-01, -4.23378129676068470921e-01,
-4.23243652734718089903e-01, -4.23109233439634191409e-01,
-4.22974880838154820850e-01, -4.22840594971471805952e-01,
-4.22706366627480289999e-01, -4.22572210261666414421e-01,
-4.22438110791802323707e-01, -4.22304080563701000894e-01,
-4.22170107628079882556e-01, -4.22036205084515114727e-01,
-4.21902366011597140805e-01, -4.21768582643646250396e-01,
-4.21634870613048051702e-01, -4.21501219859424458569e-01,
-4.21367632640160527657e-01, -4.21234109986093563371e-01,
-4.21100645516489680009e-01, -4.20967252547576220589e-01,
-4.20833917722789996319e-01, -4.20700647624544010750e-01,
-4.20567440455620111806e-01, -4.20434296822478292821e-01,
-4.20301216096496510488e-01, -4.20168200185702556126e-01,
-4.20035242086608417988e-01, -4.19902356729265902047e-01,
-4.19769524924569870095e-01, -4.19636763795404710287e-01,
-4.19504057566950971925e-01, -4.19371418687989383489e-01,
-4.19238846665829001381e-01, -4.19106331022453093560e-01,
-4.18973880635006290518e-01, -4.18841492824669647810e-01,
-4.18709169429573591081e-01, -4.18576905776015473215e-01,
-4.18444707544804173072e-01, -4.18312567862278439357e-01,
-4.18180497366403225445e-01, -4.18048482730721870926e-01,
-4.17916533095482711779e-01, -4.17784647577891687931e-01,
-4.17652820568875982055e-01, -4.17521064211650472231e-01,
-4.17389357894170531793e-01, -4.17257727217915985740e-01,
-4.17126146268366360115e-01, -4.16994637222769082285e-01,
-4.16863181990139164412e-01, -4.16731797229556111262e-01,
-4.16600467923299966344e-01, -4.16469203955557143448e-01,
-4.16338003159045233481e-01, -4.16206864318706237782e-01,
-4.16075783286184552878e-01, -4.15944766694088974290e-01,
-4.15813814512082768893e-01, -4.15682920228903296511e-01,
-4.15552087568195671619e-01, -4.15421319322513860062e-01,
-4.15290611773867390788e-01, -4.15159965825792676153e-01,
-4.15029381582135814543e-01, -4.14898857723975444944e-01,
-4.14768399423150135874e-01, -4.14637998487099423972e-01,
-4.14507660162483249078e-01, -4.14377382831094154270e-01,
-4.14247167719101527794e-01, -4.14117011540035551143e-01,
-4.13986926213605943570e-01, -4.13856889699186047960e-01,
-4.13726922360217130858e-01, -4.13597009487045419451e-01,
-4.13467167203102670126e-01, -4.13337379251928205282e-01,
-4.13207649832448620231e-01, -4.13077989581290716536e-01,
-4.12948385280632379590e-01, -4.12818845637522802150e-01,
-4.12689360217458056646e-01, -4.12559939699663091872e-01,
-4.12430585329354448820e-01, -4.12301281446441181266e-01,
-4.12172044742586951571e-01, -4.12042868814711638059e-01,
-4.11913751407601558263e-01, -4.11784696769319558118e-01,
-4.11655701338700052982e-01, -4.11526763936471140504e-01,
-4.11397892840885515131e-01, -4.11269078469947424459e-01,
-4.11140328521643949600e-01, -4.11011632961894024518e-01,
-4.10883001877293430049e-01, -4.10754427307281178017e-01,
-4.10625919831635100010e-01, -4.10497467443546093513e-01,
-4.10369074062860494934e-01, -4.10240747192873400628e-01,
-4.10112475252298658290e-01, -4.09984263535373982812e-01,
-4.09856113622305340272e-01, -4.09728025073901991338e-01,
-4.09599998066721149304e-01, -4.09472021157853860451e-01,
-4.09344117590636047410e-01, -4.09216261713988505022e-01,
-4.09088477009537043738e-01, -4.08960739905341819078e-01,
-4.08833076504052150835e-01, -4.08705461846365136758e-01,
-4.08577913787489366282e-01, -4.08450419393505292920e-01,
-4.08322990193140944459e-01, -4.08195615357145324964e-01,
-4.08068304322052877176e-01, -4.07941052522718949902e-01,
-4.07813857607316032627e-01, -4.07686722372428311800e-01,
-4.07559649159417780595e-01, -4.07432636982122509117e-01,
-4.07305676267957994519e-01, -4.07178783941681832204e-01,
-4.07051946580331669434e-01, -4.06925167423387412757e-01,
-4.06798446935890845033e-01, -4.06671791194066489794e-01,
-4.06545186603844865836e-01, -4.06418647937667909531e-01,
-4.06292163227448155371e-01, -4.06165743221352681935e-01,
-4.06039379246542819768e-01, -4.05913072894464155294e-01,
-4.05786826472172346136e-01, -4.05660640335870792406e-01,
-4.05534510753690069507e-01, -4.05408441121033802368e-01,
-4.05282432764027089611e-01, -4.05156476982766022843e-01,
-4.05030584899000456467e-01, -4.04904754253246346174e-01,
-4.04778971785819452478e-01, -4.04653259267328757609e-01,
-4.04527598754375772305e-01, -4.04401995546463499664e-01,
-4.04276457564847535586e-01, -4.04150970176745560902e-01,
-4.04025550464417959606e-01, -4.03900178259218922694e-01,
-4.03774872449987054512e-01, -4.03649622353497550264e-01,
-4.03524429462068900953e-01, -4.03399298489652113897e-01,
-4.03274220263995841762e-01, -4.03149204408413008860e-01,
-4.03024243953643779292e-01, -4.02899345977544842690e-01,
-4.02774500313819894259e-01, -4.02649718198055062146e-01,
-4.02524987205944762003e-01, -4.02400323447383079234e-01,
-4.02275708434712164774e-01, -4.02151155305185303845e-01,
-4.02026663525060001803e-01, -4.01902222092053285074e-01,
-4.01777842021426634389e-01, -4.01653523782029453493e-01,
-4.01529254483203368320e-01, -4.01405051691118952562e-01,
-4.01280902735236921774e-01, -4.01156807203930376726e-01,
-4.01032779414245976746e-01, -4.00908796037237169507e-01,
-4.00784880192289361123e-01, -4.00661018610160790665e-01,
-4.00537218896692692738e-01, -4.00413463897760724119e-01,
-4.00289781096409003069e-01, -4.00166144769810827597e-01,
-4.00042574446873522298e-01, -3.99919051262408564718e-01,
-3.99795597620649201254e-01, -3.99672187473334661334e-01,
-3.99548846729920414944e-01, -3.99425553680199330042e-01,
-3.99302324552061438379e-01, -3.99179149671766264618e-01,
-3.99056029154643832069e-01, -3.98932972213114744875e-01,
-3.98809964233907909836e-01, -3.98687020930074687008e-01,
-3.98564127590293748593e-01, -3.98441293819186026504e-01,
-3.98318518261330523078e-01, -3.98195796733791018696e-01,
-3.98073136147862105538e-01, -3.97950524217172363350e-01,
-3.97827980824171201224e-01, -3.97705483428916706234e-01,
-3.97583046429371866903e-01, -3.97460668301239106182e-01,
-3.97338340743746409878e-01, -3.97216076132537621035e-01,
-3.97093866793421013117e-01, -3.96971708695779135212e-01,
-3.96849614460402178029e-01, -3.96727571162359238244e-01,
-3.96605584352971551887e-01, -3.96483655927755584969e-01,
-3.96361783929194744225e-01, -3.96239963115969096030e-01,
-3.96118205235003517650e-01, -3.95996502067531230828e-01,
-3.95874852389952291976e-01, -3.95753258139562358320e-01,
-3.95631723966650583613e-01, -3.95510240508634480783e-01,
-3.95388818213813331148e-01, -3.95267447003314842391e-01,
-3.95146134392586834139e-01, -3.95024882750451555857e-01,
-3.94903675086172745168e-01, -3.94782532290389842622e-01,
-3.94661443670635547765e-01, -3.94540408754397275981e-01,
-3.94419428948322492445e-01, -3.94298510274204649928e-01,
-3.94177638414093090002e-01, -3.94056831090384751537e-01,
-3.93936076434925896983e-01, -3.93815370670321740487e-01,
-3.93694729598434378648e-01, -3.93574138492694181046e-01,
-3.93453606929904053935e-01, -3.93333122505293453219e-01,
-3.93212702909399636209e-01, -3.93092334488327865838e-01,
-3.92972020639507368944e-01, -3.92851761427115364622e-01,
-3.92731564372885089131e-01, -3.92611410501577051679e-01,
-3.92491323488932619679e-01, -3.92371283486580180178e-01,
-3.92251301508781347049e-01, -3.92131375698602735458e-01,
-3.92011502469516659453e-01, -3.91891686848696019219e-01,
-3.91771923489848072908e-01, -3.91652217575099825808e-01,
-3.91532564898107005025e-01, -3.91412965926249023507e-01,
-3.91293422996351725196e-01, -3.91173937469604160455e-01,
-3.91054501564423617754e-01, -3.90935122694210157590e-01,
-3.90815801338688262323e-01, -3.90696528165559997525e-01,
-3.90577317672550716754e-01, -3.90458154728669848410e-01,
-3.90339051832541139575e-01, -3.90219996472402241849e-01,
-3.90101003844937177512e-01, -3.89982059202784614449e-01,
-3.89863172811093283698e-01, -3.89744340708371272974e-01,
-3.89625557299567049085e-01, -3.89506837750507151075e-01,
-3.89388160520550086208e-01, -3.89269551902951205236e-01,
-3.89150984144685740951e-01, -3.89032474909371484006e-01,
-3.88914025999045953608e-01, -3.88795623717812122155e-01,
-3.88677276343736721742e-01, -3.88558986812192252991e-01,
-3.88440746279492155058e-01, -3.88322564833268879525e-01,
-3.88204433318420472077e-01, -3.88086355915981284781e-01,
-3.87968336232786370488e-01, -3.87850366836331561515e-01,
-3.87732451498057573147e-01, -3.87614593740575663627e-01,
-3.87496786877871923771e-01, -3.87379031779648164147e-01,
-3.87261331653111495754e-01, -3.87143683975602670433e-01,
-3.87026095630551292270e-01, -3.86908552782769032952e-01,
-3.86791070361966748958e-01, -3.86673636012102694970e-01,
-3.86556261875890649904e-01, -3.86438934090259422760e-01,
-3.86321662437166923887e-01, -3.86204444003594771218e-01,
-3.86087280659658360626e-01, -3.85970167837914435172e-01,
-3.85853110762150119939e-01, -3.85736104280530900379e-01,
-3.85619152600736536662e-01, -3.85502255219753564575e-01,
-3.85385409941956580404e-01, -3.85268614876988935158e-01,
-3.85151879781903239142e-01, -3.85035189870587046812e-01,
-3.84918561002825287964e-01, -3.84801978053202931029e-01,
-3.84685452135982874911e-01, -3.84568976271269957756e-01,
-3.84452556088511587795e-01, -3.84336187225683634239e-01,
-3.84219870325564816227e-01, -3.84103607179063666344e-01,
-3.83987401155638841121e-01, -3.83871236986547181846e-01,
-3.83755138849689481084e-01, -3.83639081181560870348e-01,
-3.83523086178925165513e-01, -3.83407135321715386578e-01,
-3.83291246965823451109e-01, -3.83175399735360855402e-01,
-3.83059616074506559258e-01, -3.82943872285916475651e-01,
-3.82828196011304522361e-01, -3.82712556260513536710e-01,
-3.82596982297232990344e-01, -3.82481455112087642689e-01,
-3.82365976775404958765e-01, -3.82250558015250652133e-01,
-3.82135187376646978663e-01, -3.82019866423826903734e-01,
-3.81904600354835643827e-01, -3.81789389165001602500e-01,
-3.81674227674965782509e-01, -3.81559114255094145030e-01,
-3.81444060603281509536e-01, -3.81329055085196044761e-01,
-3.81214099012656737475e-01, -3.81099198772719693906e-01,
-3.80984349857083404167e-01, -3.80869552736027128237e-01,
-3.80754810036734891998e-01, -3.80640110780191776030e-01,
-3.80525473903531141762e-01, -3.80410879340718488528e-01,
-3.80296343715274709485e-01, -3.80181854126763640878e-01,
-3.80067423201666698684e-01, -3.79953035686236617607e-01,
-3.79838706441368301192e-01, -3.79724424804841864667e-01,
-3.79610196212900707913e-01, -3.79496020758661178895e-01,
-3.79381892633415152005e-01, -3.79267823803007442240e-01,
-3.79153794564509094567e-01, -3.79039827060307366047e-01,
-3.78925908303136715904e-01, -3.78812034572059530557e-01,
-3.78698222562220077059e-01, -3.78584453917463370498e-01,
-3.78470740663781501922e-01, -3.78357075405102438737e-01,
-3.78243464523851213865e-01, -3.78129901062271123191e-01,
-3.78016395293092943852e-01, -3.77902935434891784627e-01,
-3.77789524813024024663e-01, -3.77676173083359656424e-01,
-3.77562860648804621277e-01, -3.77449611538380969122e-01,
-3.77336405112449480015e-01, -3.77223255197060902688e-01,
-3.77110149479393752525e-01, -3.76997101032941372978e-01,
-3.76884103404164561013e-01, -3.76771146981984883517e-01,
-3.76658254312513096629e-01, -3.76545400701739807481e-01,
-3.76432606500236743852e-01, -3.76319859703210468638e-01,
-3.76207165627520656592e-01, -3.76094515010522989495e-01,
-3.75981928410063170887e-01, -3.75869377560886674949e-01,
-3.75756887910940862163e-01, -3.75644441813044516199e-01,
-3.75532050880362955336e-01, -3.75419708659158191111e-01,
-3.75307418175345186562e-01, -3.75195173779002910663e-01,
-3.75082983868028740915e-01, -3.74970842852496988318e-01,
-3.74858753518341469846e-01, -3.74746710311752939671e-01,
-3.74634721486163280169e-01, -3.74522781933396164966e-01,
-3.74410892656854399352e-01, -3.74299054751102588945e-01,
-3.74187262834480116602e-01, -3.74075526163193505802e-01,
-3.73963835445819015035e-01, -3.73852196240103518132e-01,
-3.73740606782354212179e-01, -3.73629068569595379490e-01,
-3.73517577377422416163e-01, -3.73406137430558726642e-01,
-3.73294747230386358972e-01, -3.73183408546653716531e-01,
-3.73072115798985137758e-01, -3.72960878363263692581e-01,
-3.72849686668074831175e-01, -3.72738547271451448051e-01,
-3.72627454688548187534e-01, -3.72516413124841627713e-01,
-3.72405422419142928536e-01, -3.72294479010730039459e-01,
-3.72183586127809384880e-01, -3.72072745594147935577e-01,
-3.71961946886472105689e-01, -3.71851207922366477909e-01,
-3.71740512258250443978e-01, -3.71629863047378439234e-01,
-3.71519275296183892898e-01, -3.71408719353291283394e-01,
-3.71298231762544284074e-01, -3.71187774231039768758e-01,
-3.71077385155450356624e-01, -3.70967027473084853817e-01,
-3.70856732806939093372e-01, -3.70746478782946531361e-01,
-3.70636278570893540341e-01, -3.70526124217443408870e-01,
-3.70416023190285881306e-01, -3.70305964747868754383e-01,
-3.70195962036970249720e-01, -3.70086006739641537600e-01,
-3.69976096629158424101e-01, -3.69866237754495619239e-01,
-3.69756430498219990088e-01, -3.69646667281089635892e-01,
-3.69536955685763390811e-01, -3.69427295312589665244e-01,
-3.69317680177515983431e-01, -3.69208112264662047242e-01,
-3.69098600797472087276e-01, -3.68989129249791547593e-01,
-3.68879709799311061857e-01, -3.68770343789034893422e-01,
-3.68661013669255632763e-01, -3.68551743592315017573e-01,
-3.68442521553778989940e-01, -3.68333337891429413169e-01,
-3.68224220906830435052e-01, -3.68115134111169917119e-01,
-3.68006105751164325213e-01, -3.67897126383986028397e-01,
-3.67788183182486683176e-01, -3.67679314546345559211e-01,
-3.67570457935090466606e-01, -3.67461679824609310785e-01,
-3.67352933314014973298e-01, -3.67244250124000692903e-01,
-3.67135594976164825187e-01, -3.67027010208194726104e-01,
-3.66918451154709834849e-01, -3.66809964732578319691e-01,
-3.66701497346674842870e-01, -3.66593104701923799826e-01,
-3.66484751684203469146e-01, -3.66376433638109233470e-01,
-3.66268181947639936968e-01, -3.66159965139171650339e-01,
-3.66051810667975985325e-01, -3.65943684890073561711e-01,
-3.65835627870885249369e-01, -3.65727602399674167621e-01,
-3.65619627846999917242e-01, -3.65511708644844168781e-01,
-3.65403830046463040659e-01, -3.65296001903366029939e-01,
-3.65188221908001264815e-01, -3.65080489439066679935e-01,
-3.64972809289322408510e-01, -3.64865162909030149585e-01,
-3.64757575000899281203e-01, -3.64650032359055575881e-01,
-3.64542540752545218830e-01, -3.64435090311057752199e-01,
-3.64327692395046587315e-01, -3.64220333784750771589e-01,
-3.64113033647018968786e-01, -3.64005773237700502865e-01,
-3.63898563663066054730e-01, -3.63791401593925867175e-01,
-3.63684289240767788520e-01, -3.63577221090830182693e-01,
-3.63470194632930121426e-01, -3.63363225424560787324e-01,
-3.63256298450416181822e-01, -3.63149413510743368505e-01,
-3.63042586419860147107e-01, -3.62935798823731892160e-01,
-3.62829063620695724257e-01, -3.62722369923179577267e-01,
-3.62615726031392693329e-01, -3.62509131983811849764e-01,
-3.62402579326320917197e-01, -3.62296079485166233614e-01,
-3.62189617561219312503e-01, -3.62083219373006803821e-01,
-3.61976841249034064774e-01, -3.61870542649785575939e-01,
-3.61764263515268802429e-01, -3.61658050514519047169e-01,
-3.61551866438354907451e-01, -3.61445746399240541713e-01,
-3.61339654211726535316e-01, -3.61233632449921238106e-01,
-3.61127636409807606377e-01, -3.61021690574636122673e-01,
-3.60915808770648049997e-01, -3.60809955913110880221e-01,
-3.60704146756004706553e-01, -3.60598402071625190324e-01,
-3.60492691072034687760e-01, -3.60387026729721449136e-01,
-3.60281410294411297279e-01, -3.60175846146454869956e-01,
-3.60070315514724181849e-01, -3.59964844399896066740e-01,
-3.59859414625616935712e-01, -3.59754028193141062175e-01,
-3.59648695273804441808e-01, -3.59543395532750997834e-01,
-3.59438155434585460135e-01, -3.59332956510969636632e-01,
-3.59227801467168927907e-01, -3.59122697950459535132e-01,
-3.59017635018213099318e-01, -3.58912626441924731413e-01,
-3.58807650429984748008e-01, -3.58702735673852635134e-01,
-3.58597856254525837461e-01, -3.58493020101329329385e-01,
-3.58388243767708281062e-01, -3.58283497814040119422e-01,
-3.58178816390144483250e-01, -3.58074159391590651769e-01,
-3.57969563679315316840e-01, -3.57865011320968928743e-01,
-3.57760492481530301134e-01, -3.57656042081691105672e-01,
-3.57551619680673171686e-01, -3.57447240362188889407e-01,
-3.57342928935650006039e-01, -3.57238638134922736889e-01,
-3.57134398104680117481e-01, -3.57030224939330231848e-01,
-3.56926068820051678454e-01, -3.56821978817270957229e-01,
-3.56717920226812923445e-01, -3.56613915739726006215e-01,
-3.56509953999475215358e-01, -3.56406035389410180692e-01,
-3.56302169732667595170e-01, -3.56198339705092570373e-01,
-3.56094560076684607530e-01, -3.55990833795084338220e-01,
-3.55887134299729290809e-01, -3.55783497830003514473e-01,
-3.55679895395900946831e-01, -3.55576339662835527733e-01,
-3.55472831310899628487e-01, -3.55369377306052169896e-01,
-3.55265949104364819888e-01, -3.55162586860366058517e-01,
-3.55059247906838293396e-01, -3.54955973351155584794e-01,
-3.54852730838006835690e-01, -3.54749541626036890563e-01,
-3.54646397739461272103e-01, -3.54543287471030810210e-01,
-3.54440243273785093869e-01, -3.54337214098040198529e-01,
-3.54234259930783779158e-01, -3.54131325984198830348e-01,
-3.54028459663857986151e-01, -3.53925615542254046186e-01,
-3.53822838516876625459e-01, -3.53720083832240850263e-01,
-3.53617396205830325506e-01, -3.53514730930161669153e-01,
-3.53412132710718696060e-01, -3.53309556840015970280e-01,
-3.53207048035544479703e-01, -3.53104561541793093848e-01,
-3.53002142256347628546e-01, -3.52899744751343780180e-01,
-3.52797416433685007142e-01, -3.52695102510589719724e-01,
-3.52592862987571531441e-01, -3.52490646745808322571e-01,
-3.52388486496365838097e-01, -3.52286369569029089721e-01,
-3.52184291581849773234e-01, -3.52082260381094913626e-01,
-3.51980271315386394892e-01, -3.51878335143969156462e-01,
-3.51776435832983791485e-01, -3.51674582055139683945e-01,
-3.51572777505199940418e-01, -3.51470998731403250215e-01,
-3.51369291142547612861e-01, -3.51267608313911683382e-01,
-3.51165978776873832778e-01, -3.51064379534125281523e-01,
-3.50962851691780874930e-01, -3.50861343229657896003e-01,
-3.50759887011921178690e-01, -3.50658470657319421004e-01,
-3.50557110826692830408e-01, -3.50455775609674113902e-01,
-3.50354508931666697169e-01, -3.50253256408391167032e-01,
-3.50152079892852796661e-01, -3.50050920467760762200e-01,
-3.49949817838822341276e-01, -3.49848761507466687881e-01,
-3.49747731410527840090e-01, -3.49646773595756688024e-01,
-3.49545835694024864537e-01, -3.49444947023644092443e-01,
-3.49344109735721275456e-01, -3.49243308259259088722e-01,
-3.49142558023655735777e-01, -3.49041835234058184234e-01,
-3.48941174936996667544e-01, -3.48840550148169781242e-01,
-3.48739966703028425599e-01, -3.48639428244070015417e-01,
-3.48538936717595504433e-01, -3.48438480695904329032e-01,
-3.48338081591755166500e-01, -3.48237709885298063472e-01,
-3.48137395187948728292e-01, -3.48037115629119542248e-01,
-3.47936884376261690299e-01, -3.47836692981899731070e-01,
-3.47736539716742620865e-01, -3.47636439945430031351e-01,
-3.47536378642177512521e-01, -3.47436355842000332839e-01,
-3.47336386430620702725e-01, -3.47236455533619481351e-01,
-3.47136563059466607406e-01, -3.47036724248701466955e-01,
-3.46936922934180436151e-01, -3.46837163840455153796e-01,
-3.46737444236461800351e-01, -3.46637770321905347437e-01,
-3.46538142380770852746e-01, -3.46438553077413002868e-01,
-3.46339009118686147470e-01, -3.46239513364560103081e-01,
-3.46140047668301253925e-01, -3.46040637053390887079e-01,
-3.45941266627862842320e-01, -3.45841926232616447834e-01,
-3.45742649044279204418e-01, -3.45643401922408499694e-01,
-3.45544194845180674402e-01, -3.45445043392074546684e-01,
-3.45345919970482029271e-01, -3.45246852316131280780e-01,
-3.45147824133942959790e-01, -3.45048828165022802850e-01,
-3.44949887388285747480e-01, -3.44850984202191124250e-01,
-3.44752121330503147334e-01, -3.44653305479706351111e-01,
-3.44554529451839786081e-01, -3.44455792980520536517e-01,
-3.44357104329241270335e-01, -3.44258453062156466462e-01,
-3.44159850307413472947e-01, -3.44061284340010375971e-01,
-3.43962768580065580970e-01, -3.43864283423849115273e-01,
-3.43765849162678938100e-01, -3.43667448938496766786e-01,
-3.43569107540475926488e-01, -3.43470787373464980785e-01,
-3.43372524621929409161e-01, -3.43274301550125615634e-01,
-3.43176108213079089637e-01, -3.43077979774689567627e-01,
-3.42979874931300110497e-01, -3.42881811974929173736e-01,
-3.42783803744644011147e-01, -3.42685825295640233978e-01,
-3.42587896512843437247e-01, -3.42490007504838600561e-01,
-3.42392155600618419697e-01, -3.42294361375627742561e-01,
-3.42196589902577508191e-01, -3.42098870908211949438e-01,
-3.42001187468069178799e-01, -3.41903555201509778971e-01,
-3.41805950907295763574e-01, -3.41708407067534913892e-01,
-3.41610884010259296950e-01, -3.41513418534265589255e-01,
-3.41415992523302125328e-01, -3.41318596940095919656e-01,
-3.41221263698247956331e-01, -3.41123941235853045395e-01,
-3.41026692128222064238e-01, -3.40929474098209284172e-01,
-3.40832281920377677675e-01, -3.40735156421879237243e-01,
-3.40638051278251974274e-01, -3.40540999201483007841e-01,
-3.40443982723311333594e-01, -3.40347016653051559487e-01,
-3.40250081573448603933e-01, -3.40153195640724492765e-01,
-3.40056350350729230669e-01, -3.39959539212099759453e-01,
-3.39862774342696183361e-01, -3.39766058465924336573e-01,
-3.39669368570301832833e-01, -3.39572726923125789433e-01,
-3.39476134521916550479e-01, -3.39379565109294734082e-01,
-3.39283055662032762001e-01, -3.39186573937387048083e-01,
-3.39090144874334475933e-01, -3.38993745663194734341e-01,
-3.38897397900228047884e-01, -3.38801082713558243675e-01,
-3.38704809290945374478e-01, -3.38608582104967581472e-01,
-3.38512396429294426525e-01, -3.38416244344927230614e-01,
-3.38320139902449357194e-01, -3.38224079522009613008e-01,
-3.38128041120687727883e-01, -3.38032071906532505245e-01,
-3.37936116888977844397e-01, -3.37840214711788655588e-01,
-3.37744355197438450578e-01, -3.37648540412268438615e-01,
-3.37552749916698147103e-01, -3.37457018699225064218e-01,
-3.37361316652406650896e-01, -3.37265662162290202897e-01,
-3.37170034143870922527e-01, -3.37074476199379025054e-01,
-3.36978924411865332633e-01, -3.36883434384704194553e-01,
-3.36787981731797914087e-01, -3.36692563690679236288e-01,
-3.36597193345572975876e-01, -3.36501865825531210064e-01,
-3.36406565178378635927e-01, -3.36311315380280917431e-01,
-3.36216103533976129469e-01, -3.36120934900604684259e-01,
-3.36025801332866413951e-01, -3.35930707807079897975e-01,
-3.35835664917012943764e-01, -3.35740647663017532931e-01,
-3.35645678394692614788e-01, -3.35550759768515505233e-01,
-3.35455858808978324426e-01, -3.35361015354667779675e-01,
-3.35266214785454208513e-01, -3.35171431039785638895e-01,
-3.35076715928774748754e-01, -3.34982022379972488313e-01,
-3.34887375113354646139e-01, -3.34792767024950199684e-01,
-3.34698201810667450573e-01, -3.34603671790843826273e-01,
-3.34509181636480468214e-01, -3.34414742694976452331e-01,
-3.34320327257476346272e-01, -3.34225967756777042617e-01,
-3.34131629225772386338e-01, -3.34037352044864510603e-01,
-3.33943099066518034324e-01, -3.33848889093505241110e-01,
-3.33754728765755959152e-01, -3.33660595072520660409e-01,
-3.33566506361641812450e-01, -3.33472456955982987648e-01,
-3.33378451216247595479e-01, -3.33284477376757704015e-01,
-3.33190555787780562369e-01, -3.33096661517408021425e-01,
-3.33002806887780833378e-01, -3.32909012245727220503e-01,
-3.32815228585277400608e-01, -3.32721497473031146974e-01,
-3.32627813407268324575e-01, -3.32534156828269700235e-01,
-3.32440544421407024878e-01, -3.32346973708396109526e-01,
-3.32253437917002014679e-01, -3.32159944262706452456e-01,
-3.32066493007559804251e-01, -3.31973075887878610324e-01,
-3.31879703344604704007e-01, -3.31786364229395891456e-01,
-3.31693070342937157413e-01, -3.31599807982572825082e-01,
-3.31506597806498937153e-01, -3.31413415588069915074e-01,
-3.31320270520447546225e-01, -3.31227172409371162232e-01,
-3.31134117542206174445e-01, -3.31041088612008760350e-01,
-3.30948113855706105291e-01, -3.30855164687758329656e-01,
-3.30762260158172449742e-01, -3.30669397355943583960e-01,
-3.30576568875084519927e-01, -3.30483784898807253505e-01,
-3.30391034451992582355e-01, -3.30298328900163806754e-01,
-3.30205656108088330125e-01, -3.30113030899431780796e-01,
-3.30020428466505866272e-01, -3.29927888512914768704e-01,
-3.29835366438896882002e-01, -3.29742889181185772074e-01,
-3.29650460647833876138e-01, -3.29558060621639892229e-01,
-3.29465699008131440717e-01, -3.29373378754140522240e-01,
-3.29281100518553915268e-01, -3.29188858718991950170e-01,
-3.29096652674345069300e-01, -3.29004490691431061844e-01,
-3.28912362575830508060e-01, -3.28820278446660896332e-01,
-3.28728230373613705684e-01, -3.28636217607063907398e-01,
-3.28544251075820137320e-01, -3.28452310166014393999e-01,
-3.28360421700826687896e-01, -3.28268566056630073380e-01,
-3.28176750201269351592e-01, -3.28084965886991819506e-01,
-3.27993239136963599112e-01, -3.27901518809756153949e-01,
-3.27809871689208831569e-01, -3.27718238243585369140e-01,
-3.27626655705541003361e-01, -3.27535101731415645432e-01,
-3.27443606111453289209e-01, -3.27352116731821241036e-01,
-3.27260700498897660893e-01, -3.27169298363194804846e-01,
-3.27077945505835132600e-01, -3.26986627307041588519e-01,
-3.26895344713058144670e-01, -3.26804108558686245978e-01,
-3.26712896910217709401e-01, -3.26621741964200240638e-01,
-3.26530603923376738784e-01, -3.26439520373260516628e-01,
-3.26348470176022864564e-01, -3.26257455593981449127e-01,
-3.26166488715694480316e-01, -3.26075541276352964815e-01,
-3.25984647191409737665e-01, -3.25893788470829282033e-01,
-3.25802958455817581740e-01, -3.25712179419843927963e-01,
-3.25621435983050988572e-01, -3.25530722687914997326e-01,
-3.25440054392646616055e-01, -3.25349421825410378695e-01,
-3.25258824863596140986e-01, -3.25168273269479446430e-01,
-3.25077750468310389120e-01, -3.24987268293329634172e-01,
-3.24896818338065385134e-01, -3.24806422395165106387e-01,
-3.24716046403993874314e-01, -3.24625715407476533869e-01,
-3.24535430349774611791e-01, -3.24445162411316823103e-01,
-3.24354958871001297638e-01, -3.24264771191515699389e-01,
-3.24174634484502677267e-01, -3.24084523895929232928e-01,
-3.23994459026800851742e-01, -3.23904431030612116604e-01,
-3.23814433340637919390e-01, -3.23724478718542041378e-01,
-3.23634567387877880584e-01, -3.23544685692768452245e-01,
-3.23454843329684382791e-01, -3.23365037520362053058e-01,
-3.23275269681385146736e-01, -3.23185536924682992321e-01,
-3.23095849385954259070e-01, -3.23006191762216565699e-01,
-3.22916570426217852674e-01, -3.22826997541689753035e-01,
-3.22737440432700029014e-01, -3.22647950584020293263e-01,
-3.22558466491205841908e-01, -3.22469048576812467033e-01,
-3.22379650765513003918e-01, -3.22290285177351309986e-01,
-3.22200971759220133883e-01, -3.22111685658731161652e-01,
-3.22022439283318862024e-01, -3.21933230207375298271e-01,
-3.21844055725898692266e-01, -3.21754929084502649950e-01,
-3.21665822357477593219e-01, -3.21576766946822134585e-01,
-3.21487732225476996462e-01, -3.21398764596197317189e-01,
-3.21309798481988706520e-01, -3.21220893325880607616e-01,
-3.21132011043201326395e-01, -3.21043177474382601666e-01,
-3.20954372045852032169e-01, -3.20865606507984679752e-01,
-3.20776876784593933944e-01, -3.20688187430051785398e-01,
-3.20599524303056493402e-01, -3.20510917062701183866e-01,
-3.20422328269140743728e-01, -3.20333788615695058688e-01,
-3.20245279824155071324e-01, -3.20156799610553932656e-01,
-3.20068375388967318873e-01, -3.19979966842285912243e-01,
-3.19891618417902812155e-01, -3.19803282050323323116e-01,
-3.19714993795423230161e-01, -3.19626746902161973374e-01,
-3.19538532318825452272e-01, -3.19450348299827324716e-01,
-3.19362210879227226279e-01, -3.19274102369856094263e-01,
-3.19186032782846962341e-01, -3.19098002112579104406e-01,
-3.19010000370401891612e-01, -3.18922045164797218764e-01,
-3.18834120753971106410e-01, -3.18746227793134551121e-01,
-3.18658379403236935445e-01, -3.18570567148754091313e-01,
-3.18482789299091129109e-01, -3.18395038860409540504e-01,
-3.18307345538659025586e-01, -3.18219664559104442603e-01,
-3.18132033556027371546e-01, -3.18044436174004130358e-01,
-3.17956877848706076506e-01, -3.17869353192871351155e-01,
-3.17781855968134130386e-01, -3.17694416515219568709e-01,
-3.17606986764818577385e-01, -3.17519616894733069934e-01,
-3.17432266021773434872e-01, -3.17344958093929208065e-01,
-3.17257682905915439076e-01, -3.17170457330882504809e-01,
-3.17083246433255361296e-01, -3.16996083675216477893e-01,
-3.16908959550578739339e-01, -3.16821856270166013481e-01,
-3.16734809793386418164e-01, -3.16647783478750832753e-01,
-3.16560798525840403350e-01, -3.16473851481303192212e-01,
-3.16386934958965637676e-01, -3.16300059605132577456e-01,
-3.16213212572499902109e-01, -3.16126412252237365408e-01,
-3.16039642630453532224e-01, -3.15952904668060474691e-01,
-3.15866210535302172069e-01, -3.15779532942031593290e-01,
-3.15692924175109912444e-01, -3.15606314135948418098e-01,
-3.15519774469847580356e-01, -3.15433245156387542796e-01,
-3.15346760521496294327e-01, -3.15260310337106552936e-01,
-3.15173901189560234926e-01, -3.15087516961556401984e-01,
-3.15001170832473698091e-01, -3.14914870905581789629e-01,
-3.14828593940165324394e-01, -3.14742357740590783521e-01,
-3.14656159033590621110e-01, -3.14569993107869316784e-01,
-3.14483859730134152066e-01, -3.14397764544851576751e-01,
-3.14311707559190467443e-01, -3.14225683100008756909e-01,
-3.14139691500964324256e-01, -3.14053737100567498253e-01,
-3.13967824562860597926e-01, -3.13881930893164406982e-01,
-3.13796098702669945535e-01, -3.13710269948259234951e-01,
-3.13624500080762536047e-01, -3.13538759450427528819e-01,
-3.13453044150207804641e-01, -3.13367377106299582756e-01,
-3.13281737576189989181e-01, -3.13196140900250385997e-01,
-3.13110568811249823096e-01, -3.13025034334257767910e-01,
-3.12939548339710438274e-01, -3.12854076672535452719e-01,
-3.12768655675618789669e-01, -3.12683263539456357538e-01,
-3.12597906455694685146e-01, -3.12512581467251693290e-01,
-3.12427294210809725072e-01, -3.12342047448462556414e-01,
-3.12256824495153240129e-01, -3.12171644625531874429e-01,
-3.12086492129538983775e-01, -3.12001388221020192759e-01,
-3.11916308458136226633e-01, -3.11831262339173298503e-01,
-3.11746258664567232888e-01, -3.11661275086031142045e-01,
-3.11576347492792116167e-01, -3.11491444083196455939e-01,
-3.11406566767664649831e-01, -3.11321739706168554296e-01,
-3.11236931403625127768e-01, -3.11152176625169918367e-01,
-3.11067434860568758914e-01, -3.10982743978655606920e-01,
-3.10898082421296351185e-01, -3.10813453848709397853e-01,
-3.10728865178155511106e-01, -3.10644307432114907819e-01,
-3.10559787251664443097e-01, -3.10475287050015869017e-01,
-3.10390848181504308556e-01, -3.10306412222544181212e-01,
-3.10222037402692107921e-01, -3.10137683337757430468e-01,
-3.10053363927979830361e-01, -3.09969086308332530955e-01,
-3.09884830390425081159e-01, -3.09800624689362036346e-01,
-3.09716442288341387012e-01, -3.09632295284240965927e-01,
-3.09548184558093242291e-01, -3.09464116840632463834e-01,
-3.09380064327889392484e-01, -3.09296064449780638839e-01,
-3.09212084697576772285e-01, -3.09128150621053421343e-01,
-3.09044237233321195113e-01, -3.08960374228678003039e-01,
-3.08876534872047248115e-01, -3.08792729354212536208e-01,
-3.08708965998856610380e-01, -3.08625223672207793513e-01,
-3.08541533882186080895e-01, -3.08457858786108374272e-01,
-3.08374228839820352377e-01, -3.08290627117847271244e-01,
-3.08207068514500914791e-01, -3.08123532729750682080e-01,
-3.08040041365923500383e-01, -3.07956573017225843092e-01,
-3.07873147001021363334e-01, -3.07789752157132778798e-01,
-3.07706391457163164205e-01, -3.07623064174878169119e-01,
-3.07539770243611898515e-01, -3.07456510656262227421e-01,
-3.07373281507903273191e-01, -3.07290097425341190984e-01,
-3.07206926158018700512e-01, -3.07123815026133561989e-01,
-3.07040718758160802171e-01, -3.06957659361293877520e-01,
-3.06874638781767350437e-01, -3.06791649579191139097e-01,
-3.06708697217149606207e-01, -3.06625767281695216226e-01,
-3.06542889613291458240e-01, -3.06460026319258171945e-01,
-3.06377209722884624732e-01, -3.06294415478919834772e-01,
-3.06211663941594436356e-01, -3.06128942742720511205e-01,
-3.06046258649077307368e-01, -3.05963596961736250535e-01,
-3.05880987357890266054e-01, -3.05798392882921377112e-01,
-3.05715842271141458042e-01, -3.05633324595146305125e-01,
-3.05550832478499623246e-01, -3.05468384002608395189e-01,
-3.05385958921764844032e-01, -3.05303575433909624159e-01,
-3.05221225696471032407e-01, -3.05138900530053658322e-01,
-3.05056622143069278152e-01, -3.04974355584749501347e-01,
-3.04892151394531185638e-01, -3.04809954124143744902e-01,
-3.04727800916781976781e-01, -3.04645688054904606457e-01,
-3.04563593265481658001e-01, -3.04481542302949492740e-01,
-3.04399521477817680548e-01, -3.04317537441869623294e-01,
-3.04235577277462310164e-01, -3.04153663651642758303e-01,
-3.04071763517348936379e-01, -3.03989919340557523952e-01,
-3.03908083711389997994e-01, -3.03826314396417218600e-01,
-3.03744539497943111250e-01, -3.03662832377988356480e-01,
-3.03581127948359397184e-01, -3.03499479089358148443e-01,
-3.03417851126680404583e-01, -3.03336262822015090279e-01,
-3.03254696154652281237e-01, -3.03173182094001791853e-01,
-3.03091681838359272572e-01, -3.03010230218165088623e-01,
-3.02928793768587167889e-01, -3.02847404463288505383e-01,
-3.02766034927674398958e-01, -3.02684717982977136153e-01,
-3.02603416774087974339e-01, -3.02522156493241933806e-01,
-3.02440917930091424104e-01, -3.02359730382049940456e-01,
-3.02278562925036298203e-01, -3.02197420550994855226e-01,
-3.02116336567971321969e-01, -3.02035262158805495325e-01,
-3.01954225173641788160e-01, -3.01873230084287569319e-01,
-3.01792253505111407463e-01, -3.01711317451606231277e-01,
-3.01630424302656741098e-01, -3.01549542527231539957e-01,
-3.01468706463603908219e-01, -3.01387899696680117145e-01,
-3.01307131196819122376e-01, -3.01226381497679440713e-01,
-3.01145674790784356745e-01, -3.01065000831607143539e-01,
-3.00984354054990355110e-01, -3.00903744614347823383e-01,
-3.00823159812924179057e-01, -3.00742617932585165619e-01,
-3.00662103246106759968e-01, -3.00581615677035562939e-01,
-3.00501171258409083276e-01, -3.00420750638014544265e-01,
-3.00340370488181684916e-01, -3.00260005823546505255e-01,
-3.00179695209751074003e-01, -3.00099398776559167512e-01,
-3.00019148032305449370e-01, -2.99938923869113693854e-01,
-2.99858726506670170142e-01, -2.99778574174106249295e-01,
-2.99698438438693370856e-01, -2.99618347746989255320e-01,
-2.99538283800717064498e-01, -2.99458246642942627069e-01,
-2.99378254399679799569e-01, -2.99298279227290464632e-01,
-2.99218347319087918379e-01, -2.99138448800683021123e-01,
-2.99058574624576745116e-01, -2.98978726151670703981e-01,
-2.98898929337599650324e-01, -2.98819146054147666280e-01,
-2.98739413451577451308e-01, -2.98659688112279053662e-01,
-2.98580017149462251247e-01, -2.98500367286606671513e-01,
-2.98420757461358987506e-01, -2.98341167551394614854e-01,
-2.98261614404881969520e-01, -2.98182095454955109481e-01,
-2.98102604120909442376e-01, -2.98023146940687377882e-01,
-2.97943726694965937973e-01, -2.97864325723094292009e-01,
-2.97784967183515603129e-01, -2.97705643158333255194e-01,
-2.97626339808948758847e-01, -2.97547075704168939581e-01,
-2.97467835110848732860e-01, -2.97388640041019391980e-01,
-2.97309462883185438020e-01, -2.97230325016071161848e-01,
-2.97151213239759015572e-01, -2.97072136623453109117e-01,
-2.96993094441996230426e-01, -2.96914080526812951266e-01,
-2.96835097925620905457e-01, -2.96756140616124208798e-01,
-2.96677229639789485915e-01, -2.96598331556529593023e-01,
-2.96519492030000386684e-01, -2.96440651252633635693e-01,
-2.96361868680595386127e-01, -2.96283100407240262975e-01,
-2.96204373196016779168e-01, -2.96125668603260061573e-01,
-2.96047011288438355336e-01, -2.95968365760827856192e-01,
-2.95889759916888317459e-01, -2.95811184716729846933e-01,
-2.95732648423452593178e-01, -2.95654127024545076985e-01,
-2.95575663603469929175e-01, -2.95497199245855601824e-01,
-2.95418792415274189533e-01, -2.95340402282260605649e-01,
-2.95262044294134995415e-01, -2.95183719842823877322e-01,
-2.95105430265042822935e-01, -2.95027168822003471593e-01,
-2.94948938780401348492e-01, -2.94870733812242991068e-01,
-2.94792575962806668866e-01, -2.94714428082456292302e-01,
-2.94636327317490787081e-01, -2.94558251639318091630e-01,
-2.94480207312523167840e-01, -2.94402191307359006878e-01,
-2.94324209478228515646e-01, -2.94246263789008088985e-01,
-2.94168340529790128812e-01, -2.94090447872844884536e-01,
-2.94012589190740691869e-01, -2.93934765172675471767e-01,
-2.93856969689289537762e-01, -2.93779204217081924000e-01,
-2.93701468979416069338e-01, -2.93623761606339073182e-01,
-2.93546091354298932519e-01, -2.93468445919199183436e-01,
-2.93390842909234894620e-01, -2.93313246547464823166e-01,
-2.93235715278232778047e-01, -2.93158185211556288063e-01,
-2.93080697000828283016e-01, -2.93003241329427011053e-01,
-2.92925814810446050185e-01, -2.92848417956391993133e-01,
-2.92771052104143891803e-01, -2.92693711393679945054e-01,
-2.92616417928207417365e-01, -2.92539133858402689015e-01,
-2.92461899071386643989e-01, -2.92384681274965418929e-01,
-2.92307502695569265683e-01, -2.92230351423153955626e-01,
-2.92153230519724305125e-01, -2.92076139647305721425e-01,
-2.91999077095791370606e-01, -2.91922050043583569678e-01,
-2.91845053838921175693e-01, -2.91768077558705263286e-01,
-2.91691147195350442001e-01, -2.91614236757522626853e-01,
-2.91537357162918120412e-01, -2.91460513083827865710e-01,
-2.91383697265133412291e-01, -2.91306911703275495107e-01,
-2.91230155667610457471e-01, -2.91153430084271469536e-01,
-2.91076731979369673908e-01, -2.91000072322327330010e-01,
-2.90923432561086381387e-01, -2.90846831230972657778e-01,
-2.90770257446225033338e-01, -2.90693713862819946847e-01,
-2.90617200742612991071e-01, -2.90540714382205189636e-01,
-2.90464269333337077317e-01, -2.90387833444186949095e-01,
-2.90311453715076384086e-01, -2.90235086055248836523e-01,
-2.90158748068700511613e-01, -2.90082458133686604818e-01,
-2.90006169836673932672e-01, -2.89929938694830635626e-01,
-2.89853723163468357527e-01, -2.89777544497205108431e-01,
-2.89701381573999106056e-01, -2.89625275275657623197e-01,
-2.89549172603960458527e-01, -2.89473110559530621977e-01,
-2.89397083545063105170e-01, -2.89321076949155042701e-01,
-2.89245110111239545070e-01, -2.89169164988470173139e-01,
-2.89093249709316657547e-01, -2.89017372154488083602e-01,
-2.88941515024419282032e-01, -2.88865694933179373294e-01,
-2.88789907427540515350e-01, -2.88714131354602387969e-01,
-2.88638411075711198706e-01, -2.88562702057091502450e-01,
-2.88487026313789418630e-01, -2.88411385022879718232e-01,
-2.88335773812758988655e-01, -2.88260186641024429566e-01,
-2.88184629697148420036e-01, -2.88109106617386423466e-01,
-2.88033619018986331017e-01, -2.87958134444958546716e-01,
-2.87882714050788857119e-01, -2.87807302133715914305e-01,
-2.87731926238848467747e-01, -2.87656576591996948622e-01,
-2.87581264744810216616e-01, -2.87505976616624470132e-01,
-2.87430712274962751884e-01, -2.87355485530396581595e-01,
-2.87280285776600030623e-01, -2.87205119276563780595e-01,
-2.87129971584651144667e-01, -2.87054871868676564350e-01,
-2.86979784958243722137e-01, -2.86904732960156783061e-01,
-2.86829707321078597460e-01, -2.86754720147553709975e-01,
-2.86679753918483326558e-01, -2.86604821908234108641e-01,
-2.86529910892180106341e-01, -2.86455038142716500449e-01,
-2.86380192498372043719e-01, -2.86305378980894975616e-01,
-2.86230588664763641038e-01, -2.86155829878574685665e-01,
-2.86081100585204695097e-01, -2.86006400604550847788e-01,
-2.85931732694147622276e-01, -2.85857086003960036980e-01,
-2.85782478824851915444e-01, -2.85707893546886637637e-01,
-2.85633337615462501446e-01, -2.85558821210665669810e-01,
-2.85484318518494484263e-01, -2.85409855559644154432e-01,
-2.85335421120561150143e-01, -2.85261011683021981078e-01,
-2.85186630181732847511e-01, -2.85112290747834062898e-01,
-2.85037956273799741869e-01, -2.84963671651626282433e-01,
-2.84889406179563264843e-01, -2.84815170717389598565e-01,
-2.84740974879482466875e-01, -2.84666791700296184509e-01,
-2.84592652372410381822e-01, -2.84518526146278427635e-01,
-2.84444437772280900312e-01, -2.84370386053668045001e-01,
-2.84296351027058247229e-01, -2.84222346687502624984e-01,
-2.84148381721661014154e-01, -2.84074429739585632149e-01,
-2.84000520559181790503e-01, -2.83926628354001953092e-01,
-2.83852781908446982762e-01, -2.83778936614844545794e-01,
-2.83705152712516173175e-01, -2.83631367962298708285e-01,
-2.83557636971072390963e-01, -2.83483915309188483356e-01,
-2.83410236681394867020e-01, -2.83336577753573792826e-01,
-2.83262953453964461126e-01, -2.83189349755469832459e-01,
-2.83115785486497573142e-01, -2.83042244063997028292e-01,
-2.82968728288279902650e-01, -2.82895243541149921107e-01,
-2.82821787846822048085e-01, -2.82748363726633200610e-01,
-2.82674963071020246552e-01, -2.82601593445157617257e-01,
-2.82528255049651622066e-01, -2.82454939516903369423e-01,
-2.82381657764960047885e-01, -2.82308396840973641062e-01,
-2.82235175286546957629e-01, -2.82161976591600693887e-01,
-2.82088803551365452371e-01, -2.82015661494998293168e-01,
-2.81942548662382108660e-01, -2.81869466764828491279e-01,
-2.81796410717207790331e-01, -2.81723376796985280901e-01,
-2.81650384979429901922e-01, -2.81577403789483815544e-01,
-2.81504472096883839871e-01, -2.81431555304708314047e-01,
-2.81358663523939900308e-01, -2.81285813259310846224e-01,
-2.81212973084393191847e-01, -2.81140185144941545659e-01,
-2.81067401691332485747e-01, -2.80994659817595748841e-01,
-2.80921948304203306090e-01, -2.80849252583495911928e-01,
-2.80776597442154440820e-01, -2.80703965356340401360e-01,
-2.80631356931243525210e-01, -2.80558787269943044063e-01,
-2.80486240058415603471e-01, -2.80413720746192474120e-01,
-2.80341223849171372606e-01, -2.80268765854230661461e-01,
-2.80196331001442144881e-01, -2.80123921140157272625e-01,
-2.80051544632897941867e-01, -2.79979188531967460030e-01,
-2.79906873913888409877e-01, -2.79834574123750678964e-01,
-2.79762307649446984037e-01, -2.79690071897800485168e-01,
-2.79617858753625214696e-01, -2.79545680919100536510e-01,
-2.79473518052436586956e-01, -2.79401394115129930729e-01,
-2.79329300658209156438e-01, -2.79257225164321998268e-01,
-2.79185181448365571377e-01, -2.79113171471586540839e-01,
-2.79041173574101741828e-01, -2.78969227730713253965e-01,
-2.78897285109063419739e-01, -2.78825389305071169588e-01,
-2.78753504174386379511e-01, -2.78681663643264965202e-01,
-2.78609835206258815710e-01, -2.78538047903678309680e-01,
-2.78466285134956692549e-01, -2.78394539558566300741e-01,
-2.78322834789442918879e-01, -2.78251150764596166809e-01,
-2.78179499417568476538e-01, -2.78107875428922401984e-01,
-2.78036265791123227142e-01, -2.77964705502005637872e-01,
-2.77893156984732658810e-01, -2.77821646141850175926e-01,
-2.77750151643495701848e-01, -2.77678688203089274467e-01,
-2.77607263000297366240e-01, -2.77535854954775007553e-01,
-2.77464474153011120272e-01, -2.77393123681135944647e-01,
-2.77321803459881777165e-01, -2.77250510720189358160e-01,
-2.77179234265821305971e-01, -2.77107999299044949204e-01,
-2.77036783262253505367e-01, -2.76965606480123249789e-01,
-2.76894432563297876460e-01, -2.76823319689300406665e-01,
-2.76752205647846361014e-01, -2.76681124640357545275e-01,
-2.76610091478398878451e-01, -2.76539057417772293768e-01,
-2.76468068513254561225e-01, -2.76397101048645399413e-01,
-2.76326159130485415893e-01, -2.76255250048812850405e-01,
-2.76184362888675982717e-01, -2.76113511668101052621e-01,
-2.76042673581677333594e-01, -2.75971881129537299771e-01,
-2.75901094171787597542e-01, -2.75830351360901726565e-01,
-2.75759627633846315931e-01, -2.75688939886797879097e-01,
-2.75618267949825468399e-01, -2.75547630902992390922e-01,
-2.75477017299460613664e-01, -2.75406431494776671176e-01,
-2.75335867513592791322e-01, -2.75265344901753472584e-01,
-2.75194836154711519605e-01, -2.75124364689586453636e-01,
-2.75053909045930800037e-01, -2.74983486944931576623e-01,
-2.74913093665771546270e-01, -2.74842730370532195572e-01,
-2.74772374779963690639e-01, -2.74702070145500243381e-01,
-2.74631777499363627371e-01, -2.74561520054265151281e-01,
-2.74491288630621499411e-01, -2.74421074382313445739e-01,
-2.74350899521658420088e-01, -2.74280751100732245185e-01,
-2.74210613995430008138e-01, -2.74140516946612011751e-01,
-2.74070449521909065282e-01, -2.74000402358196282204e-01,
-2.73930378636858429253e-01, -2.73860397347223338826e-01,
-2.73790424054078607163e-01, -2.73720488101978187689e-01,
-2.73650573603144597890e-01, -2.73580692412392134649e-01,
-2.73510835349982106557e-01, -2.73441004928314412847e-01,
-2.73371200277527037770e-01, -2.73301422364668755716e-01,
-2.73231668191406429358e-01, -2.73161948784023778103e-01,
-2.73092245387460519357e-01, -2.73022577292190926634e-01,
-2.72952930794861547970e-01, -2.72883319066670071429e-01,
-2.72813725477921487084e-01, -2.72744158672713621350e-01,
-2.72674623056092968465e-01, -2.72605114715516849699e-01,
-2.72535622544367805986e-01, -2.72466172529916839107e-01,
-2.72396738884922551271e-01, -2.72327331715854548122e-01,
-2.72257958735816929519e-01, -2.72188601337665814217e-01,
-2.72119281533388934768e-01, -2.72049974585663156823e-01,
-2.71980712728309426129e-01, -2.71911458818592688402e-01,
-2.71842239786664607859e-01, -2.71773052109879453830e-01,
-2.71703882948668151709e-01, -2.71634742480469149051e-01,
-2.71565625186839798566e-01, -2.71496542964112241858e-01,
-2.71427476097141573419e-01, -2.71358446846692968890e-01,
-2.71289430588333102534e-01, -2.71220458855547019716e-01,
-2.71151497194053625606e-01, -2.71082562480524313919e-01,
-2.71013666366038519229e-01, -2.70944790073090580051e-01,
-2.70875930005398501965e-01, -2.70807119325596090675e-01,
-2.70738318386396559223e-01, -2.70669540855605239571e-01,
-2.70600794061028715465e-01, -2.70532079727119401102e-01,
-2.70463383628260722880e-01, -2.70394716238982646406e-01,
-2.70326072238524450775e-01, -2.70257462435398387868e-01,
-2.70188871268058794506e-01, -2.70120305470691102201e-01,
-2.70051776019842759702e-01, -2.69983254626878887983e-01,
-2.69914776414566681684e-01, -2.69846318587439903958e-01,
-2.69777892501111837831e-01, -2.69709475528596143157e-01,
-2.69641102118741149418e-01, -2.69572746510107319473e-01,
-2.69504410244378711514e-01, -2.69436112916259018490e-01,
-2.69367841660474394150e-01, -2.69299583639932893497e-01,
-2.69231358364793171845e-01, -2.69163167686737425655e-01,
-2.69094984688878380297e-01, -2.69026848131857065916e-01,
-2.68958719296964632317e-01, -2.68890624891427842957e-01,
-2.68822563860274088565e-01, -2.68754513716166654191e-01,
-2.68686498408199803123e-01, -2.68618511682558958054e-01,
-2.68550532253665763527e-01, -2.68482606814164914688e-01,
-2.68414681637764829247e-01, -2.68346790826536729657e-01,
-2.68278941105454360461e-01, -2.68211093824292923227e-01,
-2.68143285100269301857e-01, -2.68075498521707644706e-01,
-2.68007741266353127774e-01, -2.67940001034900732169e-01,
-2.67872297495083122598e-01, -2.67804608978758684756e-01,
-2.67736957787277685128e-01, -2.67669321086863643000e-01,
-2.67601723207789465864e-01, -2.67534134366222919876e-01,
-2.67466582311995049182e-01, -2.67399052884839394384e-01,
-2.67331552624248569572e-01, -2.67264069532518910854e-01,
-2.67196622709230169335e-01, -2.67129192457251085635e-01,
-2.67061793762043198086e-01, -2.66994408730633570048e-01,
-2.66927071597710174888e-01, -2.66859730372719650138e-01,
-2.66792447024478796003e-01, -2.66725159778724463244e-01,
-2.66657919653241259894e-01, -2.66590696109862967944e-01,
-2.66523493228245089703e-01, -2.66456325227931167809e-01,
-2.66389175854575221969e-01, -2.66322051202534382242e-01,
-2.66254965500467566386e-01, -2.66187878091123653057e-01,
-2.66120847967881601903e-01, -2.66053813924927218260e-01,
-2.65986827681687298952e-01, -2.65919855324977860711e-01,
-2.65852913732882611964e-01, -2.65785991657992881620e-01,
-2.65719094860117854839e-01, -2.65652233899170586717e-01,
-2.65585383127432239636e-01, -2.65518567520639292567e-01,
-2.65451779878790095069e-01, -2.65385001674412923656e-01,
-2.65318269513913018720e-01, -2.65251544906108194244e-01,
-2.65184855802354790821e-01, -2.65118195943634726852e-01,
-2.65051540062922641461e-01, -2.64984928432112298857e-01,
-2.64918336989363401024e-01, -2.64851777006659072633e-01,
-2.64785227457907834658e-01, -2.64718716472008730456e-01,
-2.64652219614681993853e-01, -2.64585761790664397708e-01,
-2.64519312518772475862e-01, -2.64452901763777392663e-01,
-2.64386507203004050837e-01, -2.64320143458897371946e-01,
-2.64253796716094724317e-01, -2.64187485261860310892e-01,
-2.64121194465983144539e-01, -2.64054919858559333790e-01,
-2.63988693949415653695e-01, -2.63922458224374323343e-01,
-2.63856280119868835676e-01, -2.63790104866535146666e-01,
-2.63723972346687929313e-01, -2.63657844855657130800e-01,
-2.63591766274582917085e-01, -2.63525688190542506373e-01,
-2.63459648615377350911e-01, -2.63393633321611475573e-01,
-2.63327638855565759890e-01, -2.63261670907691203158e-01,
-2.63195732521604275345e-01, -2.63129805832387764220e-01,
-2.63063914552611355369e-01, -2.62998048752138335882e-01,
-2.62932202087204025531e-01, -2.62866387511262566967e-01,
-2.62800581906003083432e-01, -2.62734820087732301452e-01,
-2.62669075316500522099e-01, -2.62603352680575163891e-01,
-2.62537658566835474527e-01, -2.62471984691239335064e-01,
-2.62406335451333905251e-01, -2.62340723892714733356e-01,
-2.62275115787194479378e-01, -2.62209545594959014814e-01,
-2.62143999110420133913e-01, -2.62078476344002386789e-01,
-2.62012969107854654105e-01, -2.61947510142956141443e-01,
-2.61882043728466684662e-01, -2.61816625896317489719e-01,
-2.61751222350074252976e-01, -2.61685847188317666223e-01,
-2.61620500664901001198e-01, -2.61555167665830534673e-01,
-2.61489863689744250763e-01, -2.61424586559567295740e-01,
-2.61359329484961766532e-01, -2.61294099452612282874e-01,
-2.61228897657859171488e-01, -2.61163712332657116377e-01,
-2.61098567002105375057e-01, -2.61033424037335481938e-01,
-2.60968321021755156330e-01, -2.60903234657569038646e-01,
-2.60838175849067432921e-01, -2.60773146628625773769e-01,
-2.60708127962452462789e-01, -2.60643149249854877425e-01,
-2.60578178982620423110e-01, -2.60513246739066617330e-01,
-2.60448332769361301509e-01, -2.60383441791032177459e-01,
-2.60318574683800485481e-01, -2.60253745562995741913e-01,
-2.60188919439319599203e-01, -2.60124132747669434274e-01,
-2.60059364144720972511e-01, -2.59994617865390797995e-01,
-2.59929898313336460447e-01, -2.59865205990752967669e-01,
-2.59800534485202572199e-01, -2.59735886592499798375e-01,
-2.59671257541824240800e-01, -2.59606663620642774681e-01,
-2.59542089153392552259e-01, -2.59477535851373675158e-01,
-2.59413012544949028726e-01, -2.59348504553108316628e-01,
-2.59284039417788769732e-01, -2.59219566355734731822e-01,
-2.59155149199322865083e-01, -2.59090739864494823408e-01,
-2.59026355096398042122e-01, -2.58961998350243305378e-01,
-2.58897661411781720986e-01, -2.58833351331056227274e-01,
-2.58769070473885531847e-01, -2.58704802326952476577e-01,
-2.58640565874222572162e-01, -2.58576346396635348146e-01,
-2.58512161434724663245e-01, -2.58448000248899634190e-01,
-2.58383843553506298285e-01, -2.58319734527267641511e-01,
-2.58255631499654580985e-01, -2.58191568567093354680e-01,
-2.58127518069633854481e-01, -2.58063489495424180920e-01,
-2.57999494903564385861e-01, -2.57935521272989909392e-01,
-2.57871563925374303050e-01, -2.57807632243347462087e-01,
-2.57743738078198836305e-01, -2.57679846993883299167e-01,
-2.57615995476324077806e-01, -2.57552161424840830861e-01,
-2.57488352052748226129e-01, -2.57424560607467600715e-01,
-2.57360806885999326976e-01, -2.57297063156403882367e-01,
-2.57233353494213945467e-01, -2.57169654032721739512e-01,
-2.57105991459742000416e-01, -2.57042349945948600531e-01,
-2.56978721417348343614e-01, -2.56915131647498573564e-01,
-2.56851552671387484139e-01, -2.56788003520280194714e-01,
-2.56724480737611615577e-01, -2.56660979118377152730e-01,
-2.56597500587418092532e-01, -2.56534042650374050076e-01,
-2.56470613359845278634e-01, -2.56407205351532829773e-01,
-2.56343817678290730733e-01, -2.56280461493001709972e-01,
-2.56217115483022284117e-01, -2.56153809042560520748e-01,
-2.56090512962653060747e-01, -2.56027247629719512112e-01,
-2.55964005410528327999e-01, -2.55900774099844519061e-01,
-2.55837587800097965296e-01, -2.55774411713771132604e-01,
-2.55711261521537225327e-01, -2.55648131649962473411e-01,
-2.55585028712108974780e-01, -2.55521954180903843046e-01,
-2.55458895551576692373e-01, -2.55395856666797982371e-01,
-2.55332857012398051211e-01, -2.55269859505869389782e-01,
-2.55206903584443867139e-01, -2.55143957988668623749e-01,
-2.55081041263898300464e-01, -2.55018155191650386371e-01,
-2.54955274100500506318e-01, -2.54892431839403521554e-01,
-2.54829608090931025721e-01, -2.54766805572358312482e-01,
-2.54704033732013002123e-01, -2.54641274411050722026e-01,
-2.54578546093037649811e-01, -2.54515837706037417743e-01,
-2.54453152702487472858e-01, -2.54390488344574172697e-01,
-2.54327852131114695577e-01, -2.54265239156395761455e-01,
-2.54202639192711965510e-01, -2.54140075704855583627e-01,
-2.54077532116588844513e-01, -2.54015006564586975912e-01,
-2.53952500726644714302e-01, -2.53890032106650342936e-01,
-2.53827573714738630173e-01, -2.53765148951257568655e-01,
-2.53702735908163778955e-01, -2.53640354113799260105e-01,
-2.53577992066322810416e-01, -2.53515653893015502351e-01,
-2.53453334586594525302e-01, -2.53391050048909827197e-01,
-2.53328764031586106675e-01, -2.53266538571049248940e-01,
-2.53204295880422258769e-01, -2.53142106256852073010e-01,
-2.53079922760821030003e-01, -2.53017773446285620942e-01,
-2.52955637740421068749e-01, -2.52893525177086520017e-01,
-2.52831440545411512133e-01, -2.52769377506761316887e-01,
-2.52707334274802852825e-01, -2.52645324333503284997e-01,
-2.52583317885069102982e-01, -2.52521353581481644568e-01,
-2.52459396019576121084e-01, -2.52397481104805143648e-01,
-2.52335567673748484285e-01, -2.52273695067666836600e-01,
-2.52211836491905649904e-01, -2.52149992728596172853e-01,
-2.52088187443868294579e-01, -2.52026392246296748745e-01,
-2.51964629980227339257e-01, -2.51902882363185642856e-01,
-2.51841154977239800594e-01, -2.51779466128333406783e-01,
-2.51717781714107968760e-01, -2.51656130431086255683e-01,
-2.51594498650761222436e-01, -2.51532889838896656087e-01,
-2.51471303760944120409e-01, -2.51409737889333739780e-01,
-2.51348202568893563935e-01, -2.51286681299622782770e-01,
-2.51225185033213394004e-01, -2.51163708814639563549e-01,
-2.51102261512313018610e-01, -2.51040834959354253186e-01,
-2.50979430603127828814e-01, -2.50918050821055227395e-01,
-2.50856684656085349161e-01, -2.50795351207259931137e-01,
-2.50734029738946484489e-01, -2.50672739391149534960e-01,
-2.50611469042967272003e-01, -2.50550221686260676801e-01,
-2.50488996474487024546e-01, -2.50427793801956899422e-01,
-2.50366612937970467456e-01, -2.50305456411016258311e-01,
-2.50244314837840708954e-01, -2.50183200871226807394e-01,
-2.50122117986780634347e-01, -2.50061039629294101783e-01,
-2.50000001488768275326e-01
};
// common/dmath.h
#define DMATH_INFINITY ((float)((1e+300 * 1e+300)))
#define DMATH_NAN ((float)(DMATH_INFINITY * 0.0F))
#define DMATH_PI 3.1415926535897932384
#define DMATH_E 2.7182818284590452354
#define DMATH_DEG2RAD 0.017453292519943295
#define DMATH_RAD2DEG 57.29577951308232
#define DMATH_EPSILON 1e-10
#define DMATH_LOG2_E 1.4426950408889634
double dmath_exp2(double x);
double dmath_log2(double x);
double dmath_exp(double x);
double dmath_exp10(double x);
double dmath_log(double x);
double dmath_log10(double x);
double dmath_pow(double base, double exp);
double dmath_sqrt(double x);
double dmath_cbrt(double x);
void dmath_sincos(double x, double* sin, double* cos);
double dmath_sin(double x);
double dmath_cos(double x);
double dmath_tan(double x);
double dmath_asin(double x);
double dmath_acos(double x);
double dmath_atan(double x);
double dmath_atan2(double y, double x);
int dmath_isinf(double x);
int dmath_isnan(double x);
int dmath_isnormal(double x);
int dmath_isfinite(double x);
double dmath_fmod(double x, double y);
double dmath_copysign(double x, double y);
double dmath_fabs(double x);
double dmath_ceil(double x);
double dmath_floor(double x);
double dmath_trunc(double x);
double dmath_modf(double x, double* intpart);
double dmath_fmin(double x, double y);
double dmath_fmax(double x, double y);
// common/memorypool.h
typedef struct FixedMemoryPool {
int BlockSize;
int BlockCount;
char* data;
char* data_end;
int exceeded_bytes;
char** _free_list;
int _free_list_length;
} FixedMemoryPool;
void FixedMemoryPool__ctor(FixedMemoryPool* self, int BlockSize, int BlockCount);
void FixedMemoryPool__dtor(FixedMemoryPool* self);
void* FixedMemoryPool__alloc(FixedMemoryPool* self);
void FixedMemoryPool__dealloc(FixedMemoryPool* self, void* p);
// common/name.h
#ifdef __cplusplus
extern "C" {
#endif
void pk_names_initialize();
void pk_names_finalize();
#define MAGIC_METHOD(x) extern py_Name x;
#ifdef MAGIC_METHOD
// math operators
MAGIC_METHOD(__lt__)
MAGIC_METHOD(__le__)
MAGIC_METHOD(__gt__)
MAGIC_METHOD(__ge__)
/////////////////////////////
MAGIC_METHOD(__neg__)
MAGIC_METHOD(__abs__)
MAGIC_METHOD(__round__)
MAGIC_METHOD(__divmod__)
/////////////////////////////
MAGIC_METHOD(__add__)
MAGIC_METHOD(__radd__)
MAGIC_METHOD(__sub__)
MAGIC_METHOD(__rsub__)
MAGIC_METHOD(__mul__)
MAGIC_METHOD(__rmul__)
MAGIC_METHOD(__truediv__)
MAGIC_METHOD(__rtruediv__)
MAGIC_METHOD(__floordiv__)
MAGIC_METHOD(__rfloordiv__)
MAGIC_METHOD(__mod__)
MAGIC_METHOD(__rmod__)
MAGIC_METHOD(__pow__)
MAGIC_METHOD(__rpow__)
MAGIC_METHOD(__matmul__)
MAGIC_METHOD(__lshift__)
MAGIC_METHOD(__rshift__)
MAGIC_METHOD(__and__)
MAGIC_METHOD(__or__)
MAGIC_METHOD(__xor__)
/////////////////////////////
MAGIC_METHOD(__repr__)
MAGIC_METHOD(__str__)
MAGIC_METHOD(__hash__)
MAGIC_METHOD(__len__)
MAGIC_METHOD(__iter__)
MAGIC_METHOD(__next__)
MAGIC_METHOD(__contains__)
MAGIC_METHOD(__bool__)
MAGIC_METHOD(__invert__)
/////////////////////////////
MAGIC_METHOD(__eq__)
MAGIC_METHOD(__ne__)
// indexer
MAGIC_METHOD(__getitem__)
MAGIC_METHOD(__setitem__)
MAGIC_METHOD(__delitem__)
// specials
MAGIC_METHOD(__new__)
MAGIC_METHOD(__init__)
MAGIC_METHOD(__call__)
MAGIC_METHOD(__enter__)
MAGIC_METHOD(__exit__)
MAGIC_METHOD(__name__)
MAGIC_METHOD(__all__)
MAGIC_METHOD(__package__)
MAGIC_METHOD(__class__)
MAGIC_METHOD(__getattr__)
MAGIC_METHOD(__reduce__)
MAGIC_METHOD(__missing__)
#endif
#undef MAGIC_METHOD
py_Name py_namev(c11_sv name);
c11_sv py_name2sv(py_Name index);
py_Name py_name(const char* name);
const char* py_name2str(py_Name index);
#ifdef __cplusplus
} // extern "C"
#endif
// common/socket.h
#include <stdint.h>
#if PK_ENABLE_OS
typedef void* c11_socket_handler;
enum c11_address_family { C11_AF_INET = 2 };
enum c11_socket_kind { C11_SOCK_STREAM = 1 };
c11_socket_handler c11_socket_create(int family, int type, int protocol);
int c11_socket_bind(c11_socket_handler socket, const char* hostname, unsigned short port);
int c11_socket_listen(c11_socket_handler socket, int backlog);
c11_socket_handler
c11_socket_accept(c11_socket_handler socket, char* client_ip, unsigned short* client_port);
int c11_socket_connect(c11_socket_handler socket,
const char* server_ip,
unsigned short server_port);
int c11_socket_recv(c11_socket_handler socket, char* buffer, int maxsize);
int c11_socket_send(c11_socket_handler socket, const char* senddata, int datalen);
int c11_socket_close(c11_socket_handler socket);
int c11_socket_set_block(c11_socket_handler socket, int flag);
c11_socket_handler c11_socket_invalid_socket_handler();
int c11_socket_get_last_error();
#endif // PK_ENABLE_OS
// common/threads.h
#if PK_ENABLE_THREADS
#include <stdatomic.h>
#include <stdbool.h>
#if __EMSCRIPTEN__ || __APPLE__ || __linux__ || __MINGW32__
#include <pthread.h>
#define PK_USE_PTHREADS 1
typedef pthread_t c11_thrd_t;
typedef void* c11_thrd_retval_t;
typedef pthread_mutex_t c11_mutex_t;
typedef pthread_cond_t c11_cond_t;
#else
#include <threads.h>
#define PK_USE_PTHREADS 0
typedef thrd_t c11_thrd_t;
typedef int c11_thrd_retval_t;
typedef mtx_t c11_mutex_t;
typedef cnd_t c11_cond_t;
#endif
typedef c11_thrd_retval_t (*c11_thrd_func_t)(void*);
bool c11_thrd__create(c11_thrd_t* thrd, c11_thrd_func_t func, void* arg);
void c11_thrd__yield();
void c11_thrd__join(c11_thrd_t thrd);
c11_thrd_t c11_thrd__current();
bool c11_thrd__equal(c11_thrd_t a, c11_thrd_t b);
void c11_mutex__ctor(c11_mutex_t* mutex);
void c11_mutex__dtor(c11_mutex_t* mutex);
void c11_mutex__lock(c11_mutex_t* mutex);
void c11_mutex__unlock(c11_mutex_t* mutex);
void c11_cond__ctor(c11_cond_t* cond);
void c11_cond__dtor(c11_cond_t* cond);
void c11_cond__wait(c11_cond_t* cond, c11_mutex_t* mutex);
void c11_cond__signal(c11_cond_t* cond);
void c11_cond__broadcast(c11_cond_t* cond);
typedef void (*c11_thrdpool_func_t)(void* arg);
typedef struct c11_thrdpool_tasks {
atomic_int sync_val;
c11_thrdpool_func_t func;
void** args;
int length;
atomic_int current_index;
atomic_int completed_count;
} c11_thrdpool_tasks;
typedef struct c11_thrdpool_worker {
int index;
atomic_int* p_ready_workers_num;
c11_mutex_t* p_mutex;
c11_cond_t* p_cond;
c11_thrdpool_tasks* p_tasks;
c11_thrd_t thread;
} c11_thrdpool_worker;
typedef struct c11_thrdpool {
int length;
atomic_int ready_workers_num;
c11_thrdpool_worker* workers;
c11_mutex_t workers_mutex;
c11_cond_t workers_cond;
c11_thrdpool_tasks tasks;
} c11_thrdpool;
void c11_thrdpool__ctor(c11_thrdpool* pool, int length);
void c11_thrdpool__dtor(c11_thrdpool* pool);
void c11_thrdpool__map(c11_thrdpool* pool, c11_thrdpool_func_t func, void** args, int num_tasks);
void c11_thrdpool__join(c11_thrdpool* pool);
#endif
// common/utils.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define PK_REGION(name) 1
#define PK_SLICE_LOOP(i, start, stop, step) \
for(int i = start; step > 0 ? i < stop : i > stop; i += step)
// global constants
#define PK_HEX_TABLE "0123456789abcdef"
#ifdef _MSC_VER
#define c11__unreachable() __assume(0)
#else
#define c11__unreachable() __builtin_unreachable()
#endif
#define c11__abort(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
putchar('\n'); \
abort(); \
} while(0)
#define c11__rtassert(cond) \
if(!(cond)) c11__abort("assertion failed: %s", #cond)
#define c11__min(a, b) ((a) < (b) ? (a) : (b))
#define c11__max(a, b) ((a) > (b) ? (a) : (b))
#define c11__count_array(a) (sizeof(a) / sizeof(a[0]))
// ref counting
typedef struct RefCounted {
int count;
void (*dtor)(void*);
} RefCounted;
#define PK_INCREF(obj) (obj)->rc.count++
#define PK_DECREF(obj) \
do { \
if(--(obj)->rc.count == 0) { \
(obj)->rc.dtor(obj); \
PK_FREE(obj); \
} \
} while(0)
// common/algorithm.h
#include <stdbool.h>
#define c11__less(a, b) ((a) < (b))
#define c11__lower_bound(T, ptr, count, key, less, out_index) \
do { \
T* __first = ptr; \
int __len = count; \
while(__len >= 8) { \
int __l2 = __len >> 1; \
T* __m = __first + __l2; \
if(less((*__m), (key))) { \
__first = ++__m; \
__len -= __l2 + 1; \
} else { \
__len = __l2; \
} \
} \
switch(__len) { \
case 7: \
if(less(*__first, (key))) __first++; \
case 6: \
if(less(*__first, (key))) __first++; \
case 5: \
if(less(*__first, (key))) __first++; \
case 4: \
if(less(*__first, (key))) __first++; \
case 3: \
if(less(*__first, (key))) __first++; \
case 2: \
if(less(*__first, (key))) __first++; \
case 1: \
if(less(*__first, (key))) __first++; \
case 0: break; \
default: c11__unreachable(); \
} \
*(out_index) = __first - (T*)(ptr); \
} while(0)
/**
* @brief Sorts an array of elements of the same type, using the given comparison function.
* @param ptr Pointer to the first element of the array.
* @param count Number of elements in the array.
* @param elem_size Size of each element in the array.
* @param cmp Comparison function that takes two elements and returns an integer similar to
* `strcmp`.
*/
bool c11__stable_sort(void* ptr,
int length,
int elem_size,
int (*f_lt)(const void* a, const void* b, void* extra),
void* extra);
int c11__bit_length(unsigned long x);
// common/vector.h
#include <string.h>
#include <stdbool.h>
typedef struct c11_vector {
void* data;
int length;
int capacity;
int elem_size;
} c11_vector;
void c11_vector__ctor(c11_vector* self, int elem_size);
void c11_vector__dtor(c11_vector* self);
c11_vector c11_vector__copy(const c11_vector* self);
void c11_vector__reserve(c11_vector* self, int capacity);
void c11_vector__clear(c11_vector* self);
void* c11_vector__emplace(c11_vector* self);
bool c11_vector__contains(const c11_vector* self, void* elem);
void* c11_vector__submit(c11_vector* self, int* length);
void c11_vector__swap(c11_vector* self, c11_vector* other);
int c11_vector__nextcap(c11_vector* self);
void c11_vector__extend(c11_vector* self, const void* p, int size);
#define c11__getitem(T, self, index) (((T*)(self)->data)[index])
#define c11__setitem(T, self, index, value) ((T*)(self)->data)[index] = value;
#define c11__at(T, self, index) ((T*)(self)->data + index)
#define c11_vector__push(T, self, elem) \
do { \
if((self)->length == (self)->capacity) { \
c11_vector__reserve((self), c11_vector__nextcap((self))); \
} \
((T*)(self)->data)[(self)->length] = (elem); \
(self)->length++; \
} while(0)
#define c11_vector__pop(self) (--(self)->length)
#define c11_vector__back(T, self) (((T*)(self)->data)[(self)->length - 1])
#define c11_vector__insert(T, self, index, elem) \
do { \
if((self)->length == (self)->capacity) { \
c11_vector__reserve((self), c11_vector__nextcap(self)); \
} \
T* p = (T*)(self)->data + (index); \
memmove(p + 1, p, ((self)->length - (index)) * sizeof(T)); \
*p = (elem); \
(self)->length++; \
} while(0)
#define c11_vector__erase(T, self, index) \
do { \
T* p = (T*)(self)->data + (index); \
memmove(p, p + 1, ((self)->length - (index)-1) * sizeof(T)); \
(self)->length--; \
} while(0)
#define c11__reverse(T, self) \
do { \
if(!self->data) break; \
T* p = (T*)(self)->data; \
T* q = (T*)(self)->data + (self)->length - 1; \
while(p < q) { \
T tmp = *p; \
*p = *q; \
*q = tmp; \
p++; \
q--; \
} \
} while(0)
// NOTE: here we do an extra NULL check for it to avoid UB
#define c11__foreach(T, self, it) \
for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->length; it++)
// common/chunkedvector.h
typedef struct c11_chunkedvector_chunk {
int length;
int capacity;
void* data;
} c11_chunkedvector_chunk;
typedef struct c11_chunkedvector {
c11_vector /*T=c11_chunkedvector_chunk*/ chunks;
int length;
int capacity;
int elem_size;
int initial_chunks;
} c11_chunkedvector;
// chunks[0]: size=1, total_capacity=1
// chunks[1]: size=2, total_capacity=3
// chunks[2]: size=4, total_capacity=7
// chunks[3]: size=8, total_capacity=15
// chunks[4]: size=16, total_capacity=31
// chunks[5]: size=32, total_capacity=63
// ...
// chunks[n]: size=2^n, total_capacity=2^(n+1)-1
void c11_chunkedvector__ctor(c11_chunkedvector* self, int elem_size, int initial_chunks);
void c11_chunkedvector__dtor(c11_chunkedvector* self);
void* c11_chunkedvector__emplace(c11_chunkedvector* self);
void* c11_chunkedvector__at(c11_chunkedvector* self, int index);
// common/str.h
#include <stdarg.h>
/* string */
typedef struct c11_string {
// int size | char[] | '\0'
int size;
char data[]; // flexible array member
} c11_string;
c11_string* pk_tostr(py_Ref self);
/* bytes */
typedef struct c11_bytes {
int size;
unsigned char data[]; // flexible array member
} c11_bytes;
typedef struct {
int start;
int end;
char data[4];
} c11_u32_range;
bool c11_bytes__eq(c11_bytes* self, c11_bytes* other);
int c11_sv__cmp(c11_sv self, c11_sv other);
int c11_sv__cmp2(c11_sv self, const char* other);
bool c11__streq(const char* a, const char* b);
bool c11__sveq(c11_sv a, c11_sv b);
bool c11__sveq2(c11_sv a, const char* b);
c11_string* c11_string__new(const char* data);
c11_string* c11_string__new2(const char* data, int size);
c11_string* c11_string__new3(const char* fmt, ...);
void c11_string__ctor(c11_string* self, const char* data);
void c11_string__ctor2(c11_string* self, const char* data, int size);
void c11_string__ctor3(c11_string* self, int size);
c11_string* c11_string__copy(c11_string* self);
void c11_string__delete(c11_string* self);
c11_sv c11_string__sv(c11_string* self);
int c11_sv__u8_length(c11_sv self);
c11_sv c11_sv__u8_getitem(c11_sv self, int i);
c11_string* c11_sv__u8_slice(c11_sv self, int start, int stop, int step);
// general string operations
c11_sv c11_sv__slice(c11_sv sv, int start);
c11_sv c11_sv__slice2(c11_sv sv, int start, int stop);
c11_sv c11_sv__strip(c11_sv sv, c11_sv chars, bool left, bool right);
int c11_sv__index(c11_sv self, char c);
int c11_sv__rindex(c11_sv self, char c);
c11_sv c11_sv__filename(c11_sv self);
int c11_sv__index2(c11_sv self, c11_sv sub, int start);
int c11_sv__count(c11_sv self, c11_sv sub);
bool c11_sv__startswith(c11_sv self, c11_sv prefix);
bool c11_sv__endswith(c11_sv self, c11_sv suffix);
uint64_t c11_sv__hash(c11_sv self);
c11_string* c11_sv__replace(c11_sv self, char old, char new_);
c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_);
c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep);
c11_vector /* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep);
c11_vector /* T=c11_sv */ c11_sv__splitwhitespace(c11_sv self);
// misc
int c11__unicode_index_to_byte(const char* data, int i);
int c11__byte_index_to_unicode(const char* data, int n);
bool c11__is_unicode_Lo_char(int c);
const char* c11__search_u32_ranges(int c, const c11_u32_range* p, int n_ranges);
int c11__u8_header(unsigned char c, bool suppress);
int c11__u8_value(int u8bytes, const char* data);
int c11__u32_to_u8(uint32_t utf32_char, char utf8_output[4]);
char* c11_strdup(const char* str);
unsigned char* c11_memdup(const unsigned char* data, int size);
typedef enum IntParsingResult {
IntParsing_SUCCESS,
IntParsing_FAILURE,
IntParsing_OVERFLOW,
} IntParsingResult;
IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base);
// common/serialize.h
#include <stdint.h>
typedef struct c11_serializer {
c11_vector data;
} c11_serializer;
void c11_serializer__ctor(c11_serializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver);
void c11_serializer__dtor(c11_serializer* self);
void c11_serializer__write_mark(c11_serializer* self, char mark);
void c11_serializer__write_cstr(c11_serializer* self, const char*);
void c11_serializer__write_bytes(c11_serializer* self, const void* data, int size);
void* c11_serializer__submit(c11_serializer* self, int* size);
typedef struct c11_deserializer {
char error_msg[64];
const uint8_t* data;
int size;
int index;
int8_t major_ver;
int8_t minor_ver;
} c11_deserializer;
void c11_deserializer__ctor(c11_deserializer* self, const void* data, int size);
void c11_deserializer__dtor(c11_deserializer* self);
void c11_deserializer__consume_mark(c11_deserializer* self, char expected);
bool c11_deserializer__check_header(c11_deserializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver_min);
const char* c11_deserializer__read_cstr(c11_deserializer* self);
void* c11_deserializer__read_bytes(c11_deserializer* self, int size);
#define DEF_ATOMIC_INLINE_RW(name, T) \
static inline void c11_serializer__write_##name(c11_serializer* self, T value){ \
c11_serializer__write_bytes(self, &value, sizeof(T)); \
} \
static inline T c11_deserializer__read_##name(c11_deserializer* self){ \
const void* p = self->data + self->index; \
self->index += sizeof(T); \
T retval;\
memcpy(&retval, p, sizeof(T)); \
return retval; \
}
DEF_ATOMIC_INLINE_RW(i8, int8_t)
DEF_ATOMIC_INLINE_RW(i16, int16_t)
DEF_ATOMIC_INLINE_RW(i32, int32_t)
DEF_ATOMIC_INLINE_RW(i64, int64_t)
DEF_ATOMIC_INLINE_RW(f32, float)
DEF_ATOMIC_INLINE_RW(f64, double)
DEF_ATOMIC_INLINE_RW(type, py_Type)
#undef DEF_ATOMIC_INLINE_RW
// common/smallmap.h
#include <stdint.h>
#define SMALLMAP_T__HEADER
#define K py_Name
#define V int
#define NAME c11_smallmap_n2d
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__HEADER
#define SMALLMAP_T__HEADER
#define K int
#define V int
#define NAME c11_smallmap_d2d
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__HEADER
#define SMALLMAP_T__HEADER
#define K c11_sv
#define V int
#define NAME c11_smallmap_v2d
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) c11__sveq((a), (b))
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__HEADER
#define SMALLMAP_T__HEADER
#define K void*
#define V py_i64
#define NAME c11_smallmap_p2i
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__HEADER
// common/sstream.h
#include <stdint.h>
typedef struct c11_sbuf {
c11_vector data;
} c11_sbuf;
void c11_sbuf__ctor(c11_sbuf* self);
void c11_sbuf__dtor(c11_sbuf* self);
void c11_sbuf__write_int(c11_sbuf* self, int);
void c11_sbuf__write_i64(c11_sbuf* self, int64_t);
void c11_sbuf__write_f64(c11_sbuf* self, double, int precision);
void c11_sbuf__write_char(c11_sbuf* self, char);
void c11_sbuf__write_pad(c11_sbuf* self, int count, char pad);
void c11_sbuf__write_sv(c11_sbuf* self, c11_sv);
void c11_sbuf__write_cstr(c11_sbuf* self, const char*);
void c11_sbuf__write_cstrn(c11_sbuf* self, const char*, int);
void c11_sbuf__write_quoted(c11_sbuf* self, c11_sv, char quote);
void c11_sbuf__write_hex(c11_sbuf* self, unsigned char, bool non_zero);
void c11_sbuf__write_ptr(c11_sbuf* self, void*);
// Submit the stream and return the final string. The stream becomes invalid after this call
c11_string* c11_sbuf__submit(c11_sbuf* self);
void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out);
void pk_vsprintf(c11_sbuf* ss, const char* fmt, va_list args);
void pk_sprintf(c11_sbuf* ss, const char* fmt, ...);
// debugger/core.h
#if PK_ENABLE_OS
typedef enum { C11_STEP_IN, C11_STEP_OVER, C11_STEP_OUT, C11_STEP_CONTINUE } C11_STEP_MODE;
typedef enum { C11_DEBUGGER_NOSTOP, C11_DEBUGGER_STEP, C11_DEBUGGER_EXCEPTION, C11_DEBUGGER_BP} C11_STOP_REASON;
typedef enum {
C11_DEBUGGER_SUCCESS = 0,
C11_DEBUGGER_EXIT = 1,
C11_DEBUGGER_UNKNOW_ERROR = 3,
C11_DEBUGGER_FILEPATH_ERROR = 7
} C11_DEBUGGER_STATUS;
void c11_debugger_init(void);
void c11_debugger_set_step_mode(C11_STEP_MODE mode);
void c11_debugger_exception_on_trace(py_Ref exc);
C11_DEBUGGER_STATUS c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event);
const char* c11_debugger_excinfo(const char ** message);
void c11_debugger_frames(c11_sbuf* buffer);
void c11_debugger_scopes(int frameid, c11_sbuf* buffer);
bool c11_debugger_unfold_var(int var_id, c11_sbuf* buffer);
int c11_debugger_setbreakpoint(const char* filename, int lineno);
int c11_debugger_reset_breakpoints_by_source(const char* sourcesname);
C11_STOP_REASON c11_debugger_should_pause(void);
int c11_debugger_should_keep_pause(void);
#endif // PK_ENABLE_OS
// interpreter/bindings.h
bool generator__next__(int argc, py_Ref argv);
bool array2d_like_iterator__next__(int argc, py_Ref argv);
bool list_iterator__next__(int argc, py_Ref argv);
bool tuple_iterator__next__(int argc, py_Ref argv);
bool dict_items__next__(int argc, py_Ref argv);
bool range_iterator__next__(int argc, py_Ref argv);
bool str_iterator__next__(int argc, py_Ref argv);
// interpreter/modules.h
void pk__add_module_os();
void pk__add_module_sys();
void pk__add_module_io();
void pk__add_module_math();
void pk__add_module_dis();
void pk__add_module_random();
void pk__add_module_json();
void pk__add_module_gc();
void pk__add_module_time();
void pk__add_module_easing();
void pk__add_module_traceback();
void pk__add_module_enum();
void pk__add_module_inspect();
void pk__add_module_pickle();
void pk__add_module_base64();
void pk__add_module_importlib();
void pk__add_module_unicodedata();
void pk__add_module_stdc();
void pk__add_module_vmath();
void pk__add_module_array2d();
void pk__add_module_colorcvt();
void pk__add_module_conio();
void pk__add_module_lz4();
void pk__add_module_pkpy();
void pk__add_module_picoterm();
#ifdef PK_BUILD_MODULE_CUTE_PNG
void pk__add_module_cute_png();
#else
#define pk__add_module_cute_png()
#endif
#ifdef PK_BUILD_MODULE_MSGPACK
void pk__add_module_msgpack();
#else
#define pk__add_module_msgpack()
#endif
#ifdef PK_BUILD_MODULE_PERIPHERY
void py__add_module_periphery();
#else
#define py__add_module_periphery()
#endif
// interpreter/objectpool.h
#define kPoolArenaSize (120 * 1024)
#define kMultiPoolCount 5
// #define kPoolMaxBlockSize (32 * kMultiPoolCount)
typedef struct PoolArena {
int block_size;
int block_count;
int unused_length;
union {
char data[kPoolArenaSize];
int64_t _align64;
};
int unused[];
} PoolArena;
typedef struct Pool {
c11_vector /* PoolArena* */ arenas;
int available_index;
int block_size;
} Pool;
typedef struct MultiPool {
Pool pools[kMultiPoolCount];
} MultiPool;
void* MultiPool__alloc(MultiPool* self, int size);
int MultiPool__sweep_dealloc(MultiPool* self, int* out_types);
void MultiPool__ctor(MultiPool* self);
void MultiPool__dtor(MultiPool* self);
size_t MultiPool__total_allocated_bytes(MultiPool* self);
c11_string* MultiPool__summary(MultiPool* self);
// objects/base.h
typedef struct PyObject PyObject;
typedef struct VM VM;
extern _Thread_local VM* pk_current_vm;
typedef struct py_TValue {
py_Type type;
bool is_ptr;
int extra;
union {
int64_t _i64;
double _f64;
bool _bool;
py_CFunction _cfunc;
PyObject* _obj;
c11_vec2 _vec2;
c11_vec2i _vec2i;
c11_vec3 _vec3;
c11_vec3i _vec3i;
c11_vec4i _vec4i;
c11_color32 _color32;
void* _ptr;
char _chars[16];
};
} py_TValue;
// interpreter/array2d.h
typedef struct c11_array2d_like {
int n_cols;
int n_rows;
int numel;
py_Ref (*f_get)(struct c11_array2d_like* self, int col, int row);
bool (*f_set)(struct c11_array2d_like* self, int col, int row, py_Ref value);
} c11_array2d_like;
typedef struct c11_array2d_like_iterator {
c11_array2d_like* array;
int j;
int i;
} c11_array2d_like_iterator;
typedef struct c11_array2d {
c11_array2d_like header;
py_TValue* data; // slots
} c11_array2d;
typedef struct c11_array2d_view {
c11_array2d_like header;
void* ctx;
py_Ref (*f_get)(void* ctx, int col, int row);
bool (*f_set)(void* ctx, int col, int row, py_Ref value);
c11_vec2i origin;
} c11_array2d_view;
c11_array2d* c11_newarray2d(py_OutRef out, int n_cols, int n_rows);
/* chunked_array2d */
#define SMALLMAP_T__HEADER
#define K c11_vec2i
#define V py_TValue*
#define NAME c11_chunked_array2d_chunks
#define less(a, b) (a._i64 < b._i64)
#define equal(a, b) (a._i64 == b._i64)
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__HEADER
typedef struct c11_chunked_array2d {
c11_chunked_array2d_chunks chunks;
int chunk_size;
int chunk_size_log2;
int chunk_size_mask;
c11_chunked_array2d_chunks_KV last_visited;
py_TValue default_T;
bool auto_add_chunk;
} c11_chunked_array2d;
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row);
bool c11_chunked_array2d__set(c11_chunked_array2d* self, int col, int row, py_Ref value);
// interpreter/types.h
#include <stdio.h>
typedef struct {
uint64_t hash;
py_TValue key;
py_TValue val;
} DictEntry;
typedef struct {
int length;
uint32_t capacity;
uint32_t null_index_value;
bool index_is_short;
void* indices;
c11_vector /*T=DictEntry*/ entries;
} Dict;
typedef c11_vector List;
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack);
void function__gc_mark(void* ud, c11_vector* p_stack);
typedef struct {
FILE* file; // cute_png will cast the whole userdata to FILE**
const char* path;
const char* mode;
} io_FileIO;
// objects/bintree.h
typedef struct BinTreeConfig {
int (*f_cmp)(void* lhs, void* rhs);
bool need_free_key;
} BinTreeConfig;
typedef struct BinTree {
void* key;
py_TValue value;
const BinTreeConfig* config;
struct BinTree* left;
struct BinTree* right;
} BinTree;
void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config);
void BinTree__dtor(BinTree* self);
void BinTree__set(BinTree* self, void* key, py_Ref value);
py_Ref BinTree__try_get(BinTree* self, void* key);
bool BinTree__contains(BinTree* self, void* key);
void BinTree__apply_mark(BinTree* self, c11_vector* p_stack);
// objects/container.h
#include <stdint.h>
#define FIXEDHASH_T__HEADER
#define K py_Name
#define V py_TValue
#define NAME CachedNames
#if !defined(FIXEDHASH_T__HEADER) && !defined(FIXEDHASH_T__SOURCE)
#include "pocketpy/common/chunkedvector.h"
#include "pocketpy/config.h"
#include <stdint.h>
#define FIXEDHASH_T__HEADER
#define FIXEDHASH_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_fixedhash_d2f
#endif
/* Optional Input */
#ifndef hash
#define hash(a) ((uint64_t)(a))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef FIXEDHASH_T__HEADER
/* Declaration */
typedef struct {
uint64_t hash;
K key;
V val;
} KV;
typedef struct {
int length;
uint16_t indices[0x10000];
c11_chunkedvector /*T=FixedHashEntry*/ entries;
} NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V* value);
V* METHOD(try_get)(NAME* self, K key);
bool METHOD(contains)(NAME* self, K key);
#endif
#ifdef FIXEDHASH_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
self->length = 0;
memset(self->indices, 0xFF, sizeof(self->indices));
c11_chunkedvector__ctor(&self->entries, sizeof(KV), 0);
}
void METHOD(dtor)(NAME* self) { c11_chunkedvector__dtor(&self->entries); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V* value) {
uint64_t hash_value = hash(key);
int index = (uint16_t)(hash_value & 0xFFFF);
while(self->indices[index] != 0xFFFF) {
KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
if(equal(entry->key, key)) {
entry->val = *value;
return;
}
index = ((5 * index) + 1) & 0xFFFF;
}
if(self->length >= 65000) abort();
KV* kv = c11_chunkedvector__emplace(&self->entries);
kv->hash = hash_value;
kv->key = key;
kv->val = *value;
self->indices[index] = self->entries.length - 1;
self->length++;
}
V* METHOD(try_get)(NAME* self, K key) {
uint64_t hash_value = hash(key);
int index = (uint16_t)(hash_value & 0xFFFF);
while(self->indices[index] != 0xFFFF) {
KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
if(equal(entry->key, key)) return &entry->val;
index = ((5 * index) + 1) & 0xFFFF;
}
return NULL;
}
bool METHOD(contains)(NAME* self, K key) {
V* value = METHOD(try_get)(self, key);
return value != NULL;
}
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef hash
#undef FIXEDHASH_T__HEADER
// objects/iterator.h
typedef struct tuple_iterator {
py_TValue* p;
int length;
int index;
} tuple_iterator;
typedef struct list_iterator {
c11_vector* vec;
int index;
} list_iterator;
// objects/namedict.h
typedef struct NameDict_KV {
py_Name key;
py_TValue value;
} NameDict_KV;
// https://github.com/pocketpy/pocketpy/blob/v1.x/include/pocketpy/namedict.h
typedef struct NameDict {
int length;
float load_factor;
int capacity;
int critical_size;
uintptr_t mask;
NameDict_KV* items;
} NameDict;
NameDict* NameDict__new(float load_factor);
void NameDict__delete(NameDict* self);
void NameDict__ctor(NameDict* self, float load_factor);
void NameDict__dtor(NameDict* self);
py_TValue* NameDict__try_get(NameDict* self, py_Name key);
bool NameDict__contains(NameDict* self, py_Name key);
void NameDict__set(NameDict* self, py_Name key, py_TValue* value);
bool NameDict__del(NameDict* self, py_Name key);
void NameDict__clear(NameDict* self);
// objects/object.h
typedef struct PyObject {
py_Type type; // we have a duplicated type here for convenience
uint8_t size_8b;
bool gc_marked;
int slots; // number of slots in the object
char flex[];
} PyObject;
// slots >= 0, allocate N slots
// slots == -1, allocate a dict
// | HEADER | <N slots> | <userdata>
// | HEADER | <dict> | <userdata>
py_TValue* PyObject__slots(PyObject* self);
NameDict* PyObject__dict(PyObject* self);
void* PyObject__userdata(PyObject* self);
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(NameDict))
void PyObject__dtor(PyObject* self);
#define pk__mark_value(val) \
if((val)->is_ptr && !(val)->_obj->gc_marked) { \
PyObject* obj = (val)->_obj; \
obj->gc_marked = true; \
c11_vector__push(PyObject*, p_stack, obj); \
}
// interpreter/heap.h
#include <time.h>
typedef struct ManagedHeap {
MultiPool small_objects;
c11_vector /* PyObject_p */ large_objects;
c11_vector /* PyObject_p */ gc_roots;
size_t large_total_size;
int freed_ma[3];
int gc_threshold; // threshold for gc_counter
int gc_counter; // objects created since last gc
bool gc_enabled;
py_TValue debug_callback;
} ManagedHeap;
typedef struct {
int64_t start_ns;
int64_t mark_end_ns;
int64_t swpet_end_ns;
int types_length;
int* small_types;
int* large_types;
int small_freed;
int large_freed;
struct {
int before;
int after;
int upper;
int lower;
int avg_freed;
float free_ratio;
} auto_thres;
} ManagedHeapSwpetInfo;
void ManagedHeap__ctor(ManagedHeap* self);
void ManagedHeap__dtor(ManagedHeap* self);
ManagedHeapSwpetInfo* ManagedHeapSwpetInfo__new();
void ManagedHeapSwpetInfo__delete(ManagedHeapSwpetInfo* self);
int ManagedHeap__collect_hint(ManagedHeap* self);
int ManagedHeap__collect(ManagedHeap* self);
int ManagedHeap__sweep(ManagedHeap* self, ManagedHeapSwpetInfo* out_info);
#define ManagedHeap__new(self, type, slots, udsize) \
ManagedHeap__gcnew((self), (type), (slots), (udsize))
PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize);
// external implementation
void ManagedHeap__mark(ManagedHeap* self);
// interpreter/typeinfo.h
typedef struct py_TypeInfo {
py_Name name;
py_Type index;
py_Type base;
struct py_TypeInfo* base_ti;
py_TValue self;
py_GlobalRef module;
bool is_python; // is it a python class? (not derived from c object)
bool is_final; // can it be subclassed?
bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN;
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val) PY_RAISE PY_RETURN;
bool (*delattribute)(py_Ref self, py_Name name) PY_RAISE;
bool (*getunboundmethod)(py_Ref self, py_Name name) PY_RETURN;
py_TValue annotations;
py_Dtor dtor; // destructor for this type, NULL if no dtor
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
} py_TypeInfo;
py_TypeInfo* pk_typeinfo(py_Type type);
py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name);
#define pk_tpfindmagic pk_tpfindname
py_Type pk_newtype(const char* name,
py_Type base,
const py_GlobalRef module,
void (*dtor)(void*),
bool is_python,
bool is_final);
py_Type pk_newtypewithmode(py_Name name,
py_Type base,
const py_GlobalRef module,
void (*dtor)(void*),
bool is_python,
bool is_final, enum py_CompileMode mode);
// objects/sourcedata.h
#include <stdbool.h>
struct SourceData {
RefCounted rc;
enum py_CompileMode mode;
bool is_dynamic; // for exec() and eval()
c11_string* filename;
c11_string* source;
c11_vector /*T=const char* */ line_starts;
};
typedef struct SourceData* SourceData_;
SourceData_ SourceData__rcnew(const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic);
bool SourceData__get_line(const struct SourceData* self,
int lineno,
const char** st,
const char** ed);
void SourceData__snapshot(const struct SourceData* self,
c11_sbuf* ss,
int lineno,
const char* cursor,
const char* name);
// objects/codeobject.h
#include <stdbool.h>
#include <stdint.h>
#define BC_NOARG 0
#define BC_KEEPLINE -1
#define BC_RETURN_VIRTUAL 5
typedef enum FuncType {
FuncType_UNSET,
FuncType_NORMAL,
FuncType_SIMPLE,
FuncType_GENERATOR,
} FuncType;
typedef enum NameScope {
NAME_LOCAL,
NAME_GLOBAL,
} NameScope;
typedef enum CodeBlockType {
CodeBlockType_NO_BLOCK,
CodeBlockType_WHILE_LOOP,
CodeBlockType_TRY,
/* context blocks (stack-based) */
CodeBlockType_FOR_LOOP,
CodeBlockType_WITH,
/* context blocks (flag-based) */
CodeBlockType_EXCEPT,
} CodeBlockType;
typedef enum Opcode {
#define OPCODE(name) OP_##name,
#ifdef OPCODE
/**************************/
OPCODE(NO_OP)
/**************************/
OPCODE(POP_TOP)
OPCODE(DUP_TOP)
OPCODE(DUP_TOP_TWO)
OPCODE(ROT_TWO)
OPCODE(ROT_THREE)
OPCODE(PRINT_EXPR)
/**************************/
OPCODE(LOAD_CONST)
OPCODE(LOAD_NONE)
OPCODE(LOAD_TRUE)
OPCODE(LOAD_FALSE)
/**************************/
OPCODE(LOAD_SMALL_INT)
OPCODE(LOAD_NAME_AS_INT)
/**************************/
OPCODE(LOAD_ELLIPSIS)
OPCODE(LOAD_FUNCTION)
OPCODE(LOAD_NULL)
/**************************/
OPCODE(LOAD_FAST)
OPCODE(LOAD_NAME)
OPCODE(LOAD_NONLOCAL)
OPCODE(LOAD_GLOBAL)
OPCODE(LOAD_ATTR)
OPCODE(LOAD_CLASS_GLOBAL)
OPCODE(LOAD_METHOD)
OPCODE(LOAD_SUBSCR)
OPCODE(STORE_FAST)
OPCODE(STORE_NAME)
OPCODE(STORE_GLOBAL)
OPCODE(STORE_ATTR)
OPCODE(STORE_SUBSCR)
OPCODE(DELETE_FAST)
OPCODE(DELETE_NAME)
OPCODE(DELETE_GLOBAL)
OPCODE(DELETE_ATTR)
OPCODE(DELETE_SUBSCR)
/**************************/
OPCODE(BUILD_IMAG)
OPCODE(BUILD_BYTES)
OPCODE(BUILD_TUPLE)
OPCODE(BUILD_LIST)
OPCODE(BUILD_DICT)
OPCODE(BUILD_SET)
OPCODE(BUILD_SLICE)
OPCODE(BUILD_STRING)
/**************************/
OPCODE(BINARY_ADD)
OPCODE(BINARY_SUB)
OPCODE(BINARY_MUL)
OPCODE(BINARY_TRUEDIV)
OPCODE(BINARY_FLOORDIV)
OPCODE(BINARY_MOD)
OPCODE(BINARY_POW)
OPCODE(BINARY_LSHIFT)
OPCODE(BINARY_RSHIFT)
OPCODE(BINARY_AND)
OPCODE(BINARY_OR)
OPCODE(BINARY_XOR)
OPCODE(BINARY_MATMUL)
OPCODE(COMPARE_LT)
OPCODE(COMPARE_LE)
OPCODE(COMPARE_EQ)
OPCODE(COMPARE_NE)
OPCODE(COMPARE_GT)
OPCODE(COMPARE_GE)
OPCODE(IS_OP)
OPCODE(CONTAINS_OP)
/**************************/
OPCODE(JUMP_FORWARD)
OPCODE(POP_JUMP_IF_NOT_MATCH)
OPCODE(POP_JUMP_IF_FALSE)
OPCODE(POP_JUMP_IF_TRUE)
OPCODE(JUMP_IF_TRUE_OR_POP)
OPCODE(JUMP_IF_FALSE_OR_POP)
OPCODE(SHORTCUT_IF_FALSE_OR_POP)
OPCODE(LOOP_CONTINUE)
OPCODE(LOOP_BREAK)
/**************************/
OPCODE(CALL)
OPCODE(CALL_VARGS)
/**************************/
OPCODE(RETURN_VALUE)
OPCODE(YIELD_VALUE)
OPCODE(FOR_ITER_YIELD_VALUE)
/**************************/
OPCODE(LIST_APPEND)
OPCODE(DICT_ADD)
OPCODE(SET_ADD)
/**************************/
OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT)
OPCODE(UNARY_STAR)
OPCODE(UNARY_INVERT)
/**************************/
OPCODE(GET_ITER)
OPCODE(FOR_ITER)
/**************************/
OPCODE(IMPORT_PATH)
OPCODE(POP_IMPORT_STAR)
/**************************/
OPCODE(UNPACK_SEQUENCE)
OPCODE(UNPACK_EX)
/**************************/
OPCODE(BEGIN_CLASS)
OPCODE(END_CLASS)
OPCODE(STORE_CLASS_ATTR)
OPCODE(ADD_CLASS_ANNOTATION)
/**************************/
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
/**************************/
OPCODE(BEGIN_TRY)
OPCODE(END_TRY)
OPCODE(EXCEPTION_MATCH)
OPCODE(HANDLE_EXCEPTION)
OPCODE(RAISE)
OPCODE(RAISE_ASSERT)
OPCODE(RE_RAISE)
OPCODE(PUSH_EXCEPTION)
/**************************/
OPCODE(FORMAT_STRING)
/**************************/
#endif
#undef OPCODE
} Opcode;
typedef struct Bytecode {
uint16_t op;
uint16_t arg;
} Bytecode;
void Bytecode__set_signed_arg(Bytecode* self, int arg);
bool Bytecode__is_forward_jump(const Bytecode* self);
typedef struct BytecodeEx {
int32_t lineno; // line number for each bytecode
int32_t iblock; // block index
} BytecodeEx;
typedef struct CodeBlock {
int32_t type;
int32_t parent; // parent index in blocks
int32_t start; // start index of this block in codes, inclusive
int32_t end; // end index of this block in codes, exclusive
int32_t end2; // ...
} CodeBlock;
typedef struct CodeObject {
SourceData_ src;
c11_string* name;
c11_vector /*T=Bytecode*/ codes;
c11_vector /*T=CodeObjectByteCodeEx*/ codes_ex;
c11_vector /*T=py_TValue*/ consts; // constants
c11_vector /*T=py_Name*/ varnames; // local variables
c11_vector /*T=py_Name*/ names; // non-local names
int nlocals; // number of local variables
c11_smallmap_n2d varnames_inv;
c11_smallmap_n2d names_inv;
c11_vector /*T=CodeBlock*/ blocks;
c11_vector /*T=FuncDecl_*/ func_decls;
int start_line;
int end_line;
} CodeObject;
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name);
void CodeObject__dtor(CodeObject* self);
int CodeObject__add_varname(CodeObject* self, py_Name name);
int CodeObject__add_name(CodeObject* self, py_Name name);
void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack);
// Serialization
void* CodeObject__dumps(const CodeObject* co, int* size);
char* CodeObject__loads(const void* data, int size, const char* filename, CodeObject* out);
typedef struct FuncDeclKwArg {
int index; // index in co->varnames
py_Name key; // name of this argument
py_TValue value; // default value
} FuncDeclKwArg;
typedef struct FuncDecl {
RefCounted rc;
CodeObject code; // strong ref
c11_vector /*T=int32_t*/ args; // indices in co->varnames
c11_vector /*T=FuncDeclKwArg*/ kwargs; // indices in co->varnames
int starred_arg; // index in co->varnames, -1 if no *arg
int starred_kwarg; // index in co->varnames, -1 if no **kwarg
bool nested; // whether this function is nested
char* docstring;
FuncType type;
c11_smallmap_n2d kw_to_index;
} FuncDecl;
typedef FuncDecl* FuncDecl_;
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name);
bool FuncDecl__is_duplicated_arg(const FuncDecl* self, py_Name name);
void FuncDecl__add_arg(FuncDecl* self, py_Name name);
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value);
void FuncDecl__add_starred_arg(FuncDecl* self, py_Name name);
void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name);
void FuncDecl__gc_mark(const FuncDecl* self, c11_vector* p_stack);
void FuncDecl__dtor(FuncDecl* self);
// runtime function
typedef struct Function {
FuncDecl_ decl;
py_GlobalRef module; // maybe NULL, weak ref
py_TValue globals; // maybe nil, strong ref
NameDict* closure; // maybe NULL, strong ref
PyObject* clazz; // weak ref; for super()
py_CFunction cfunc; // wrapped C function; for decl-based binding
} Function;
void Function__ctor(Function* self, FuncDecl_ decl, py_GlobalRef module, py_Ref globals);
void Function__dtor(Function* self);
// https://github.com/pocketpy/pocketpy/issues/456
// Function may be created from `execdyn` and return
// Weakrefs like `.globals` and `.clazz` may invalidate
// interpreter/frame.h
void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) PY_RETURN;
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
typedef struct ValueStack {
py_TValue* sp;
py_TValue* end;
// We allocate extra places to keep `_sp` valid to detect stack overflow
py_TValue begin[PK_VM_STACK_SIZE + PK_MAX_CO_VARNAMES];
} ValueStack;
typedef struct FrameExcInfo {
int iblock; // try block index
int offset; // stack offset from p0
py_TValue exc; // handled exception
} FrameExcInfo;
typedef struct py_Frame {
struct py_Frame* f_back;
const CodeObject* co;
py_StackRef p0; // unwinding base
py_GlobalRef module;
py_Ref globals; // a module object or a dict object
py_Ref locals;
bool is_locals_special;
int ip;
c11_vector /*T=FrameExcInfo*/ exc_stack;
} py_Frame;
typedef struct SourceLocation {
SourceData_ src;
int lineno;
} SourceLocation;
py_Frame* Frame__new(const CodeObject* co,
py_StackRef p0,
py_GlobalRef module,
py_Ref globals,
py_Ref locals,
bool is_locals_special);
void Frame__delete(py_Frame* self);
int Frame__lineno(const py_Frame* self);
int Frame__iblock(const py_Frame* self);
int Frame__getglobal(py_Frame* self, py_Name name) PY_RAISE PY_RETURN;
bool Frame__setglobal(py_Frame* self, py_Name name, py_TValue* val) PY_RAISE;
int Frame__delglobal(py_Frame* self, py_Name name) PY_RAISE;
py_Ref Frame__getclosure(py_Frame* self, py_Name name);
py_StackRef Frame__getlocal_noproxy(py_Frame* self, py_Name name);
int Frame__goto_exception_handler(py_Frame* self, ValueStack*, py_Ref);
void Frame__begin_try(py_Frame* self, py_TValue* sp);
FrameExcInfo* Frame__top_exc_info(py_Frame* self);
void Frame__gc_mark(py_Frame* self, c11_vector* p_stack);
SourceLocation Frame__source_location(py_Frame* self);
// interpreter/generator.h
typedef struct Generator{
py_Frame* frame;
int state;
} Generator;
void pk_newgenerator(py_Ref out, py_Frame* frame, py_TValue* begin, py_TValue* end);
void Generator__dtor(Generator* ud);
// interpreter/line_profiler.h
#include <time.h>
typedef struct LineRecord {
py_i64 hits;
clock_t time;
} LineRecord;
typedef struct FrameRecord {
py_Frame* frame;
clock_t prev_time;
LineRecord* prev_line;
bool is_lambda;
} FrameRecord;
typedef struct LineProfiler {
c11_smallmap_p2i records; // SourceData* -> LineRecord[]
c11_vector /*T=FrameRecord*/ frame_records; // FrameRecord[]
bool enabled;
} LineProfiler;
void LineProfiler__ctor(LineProfiler* self);
void LineProfiler__dtor(LineProfiler* self);
LineRecord* LineProfiler__get_record(LineProfiler* self, SourceLocation loc);
void LineProfiler__begin(LineProfiler* self);
void LineProfiler__tracefunc_internal(LineProfiler* self, py_Frame* frame, enum py_TraceEvent event);
void LineProfiler__end(LineProfiler* self);
void LineProfiler__reset(LineProfiler* self);
c11_string* LineProfiler__get_report(LineProfiler* self);
void LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event);
// interpreter/vm.h
#include <time.h>
// TODO:
// 1. __eq__ and __ne__ fallbacks
// 2. un-cleared exception detection
// 3. super()
// 4. stack balance guanrantee
// 5. stack effect of each opcode
// 6. py_TypeInfo
typedef struct TraceInfo {
SourceLocation prev_loc;
py_TraceFunc func;
} TraceInfo;
typedef struct WatchdogInfo {
clock_t max_reset_time;
} WatchdogInfo;
typedef struct TypePointer {
py_TypeInfo* ti;
py_Dtor dtor;
} TypePointer;
typedef struct py_ModuleInfo {
c11_string* package;
c11_string* path;
py_GlobalRef self; // weakref to the original module object
} py_ModuleInfo;
typedef struct VM {
py_Frame* top_frame;
BinTree modules;
c11_vector /*TypePointer*/ types;
py_GlobalRef builtins; // builtins module
py_GlobalRef main; // __main__ module
py_Callbacks callbacks;
py_TValue last_retval;
py_TValue unhandled_exc;
int recursion_depth;
int max_recursion_depth;
py_TValue reg[14]; // users' registers
void* ctx; // user-defined context
CachedNames cached_names;
py_StackRef curr_class;
py_StackRef curr_function;
TraceInfo trace_info;
WatchdogInfo watchdog_info;
LineProfiler line_profiler;
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
FixedMemoryPool pool_frame;
ManagedHeap heap;
ValueStack stack; // put `stack` at the end for better cache locality
} VM;
void VM__ctor(VM* self);
void VM__dtor(VM* self);
int VM__index(VM* self);
void VM__push_frame(VM* self, py_Frame* frame);
void VM__pop_frame(VM* self);
bool pk__parse_int_slice(py_Ref slice,
int length,
int* restrict start,
int* restrict stop,
int* restrict step);
bool pk__normalize_index(int* index, int length);
bool pk__object_new(int argc, py_Ref argv);
bool pk_wrapper__self(int argc, py_Ref argv);
const char* pk_op2str(py_Name op);
typedef enum FrameResult {
RES_ERROR = 0,
RES_RETURN = 1,
RES_CALL = 2,
RES_YIELD = 3,
} FrameResult;
FrameResult VM__run_top_frame(VM* self);
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
const char* pk_opname(Opcode op);
int pk_arrayview(py_Ref self, py_TValue** p);
bool pk_wrapper__arrayequal(py_Type type, int argc, py_Ref argv);
bool pk_arraycontains(py_Ref self, py_Ref val);
bool pk_loadmethod(py_StackRef self, py_Name name);
bool pk_callmagic(py_Name name, int argc, py_Ref argv);
bool pk_exec(CodeObject* co, py_Ref module);
bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals);
/// Assumes [a, b] are on the stack, performs a binary op.
/// The result is stored in `self->last_retval`.
/// The stack remains unchanged.
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop);
void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte);
bool pk_format_object(VM* self, py_Ref val, c11_sv spec);
// type registration
void pk_object__register();
void pk_number__register();
py_Type pk_str__register();
py_Type pk_str_iterator__register();
py_Type pk_bytes__register();
py_Type pk_dict__register();
py_Type pk_dict_items__register();
py_Type pk_list__register();
py_Type pk_tuple__register();
py_Type pk_list_iterator__register();
py_Type pk_tuple_iterator__register();
py_Type pk_slice__register();
py_Type pk_function__register();
py_Type pk_nativefunc__register();
py_Type pk_boundmethod__register();
py_Type pk_range__register();
py_Type pk_range_iterator__register();
py_Type pk_module__register();
py_Type pk_BaseException__register();
py_Type pk_Exception__register();
py_Type pk_StopIteration__register();
py_Type pk_super__register();
py_Type pk_property__register();
py_Type pk_staticmethod__register();
py_Type pk_classmethod__register();
py_Type pk_generator__register();
py_Type pk_namedict__register();
py_Type pk_code__register();
py_GlobalRef pk_builtins__register();
/* mappingproxy */
void pk_mappingproxy__namedict(py_Ref out, py_Ref object);
// objects/error.h
typedef struct{
SourceData_ src;
int lineno;
char msg[512];
} Error;
void py_BaseException__stpush(py_Frame* frame, py_Ref, SourceData_ src, int lineno, const char* func_name);
// compiler/lexer.h
#include <stdint.h>
extern const char* TokenSymbols[];
typedef enum TokenIndex {
TK_EOF,
TK_EOL,
TK_SOF,
TK_ID,
TK_NUM,
TK_STR,
TK_FSTR_BEGIN,
TK_FSTR_CPNT,
TK_FSTR_SPEC,
TK_FSTR_END,
TK_BYTES,
TK_IMAG,
TK_INDENT,
TK_DEDENT,
/***************/
TK_IS_NOT,
TK_NOT_IN,
TK_YIELD_FROM,
/***************/
TK_ADD,
TK_IADD,
TK_SUB,
TK_ISUB,
TK_MUL,
TK_IMUL,
TK_DIV,
TK_IDIV,
TK_FLOORDIV,
TK_IFLOORDIV,
TK_MOD,
TK_IMOD,
TK_AND,
TK_IAND,
TK_OR,
TK_IOR,
TK_XOR,
TK_IXOR,
TK_LSHIFT,
TK_ILSHIFT,
TK_RSHIFT,
TK_IRSHIFT,
/***************/
TK_LPAREN,
TK_RPAREN,
TK_LBRACKET,
TK_RBRACKET,
TK_LBRACE,
TK_RBRACE,
TK_DOT,
TK_DOTDOT,
TK_DOTDOTDOT,
TK_COMMA,
TK_COLON,
TK_SEMICOLON,
TK_POW,
TK_ARROW,
TK_HASH,
TK_DECORATOR,
TK_GT,
TK_LT,
TK_ASSIGN,
TK_EQ,
TK_NE,
TK_GE,
TK_LE,
TK_INVERT,
/***************/
TK_FALSE,
TK_NONE,
TK_TRUE,
TK_AND_KW,
TK_AS,
TK_ASSERT,
TK_BREAK,
TK_CLASS,
TK_CONTINUE,
TK_DEF,
TK_DEL,
TK_ELIF,
TK_ELSE,
TK_EXCEPT,
TK_FINALLY,
TK_FOR,
TK_FROM,
TK_GLOBAL,
TK_IF,
TK_IMPORT,
TK_IN,
TK_IS,
TK_LAMBDA,
TK_MATCH,
TK_NOT_KW,
TK_OR_KW,
TK_PASS,
TK_RAISE,
TK_RETURN,
TK_TRY,
TK_WHILE,
TK_WITH,
TK_YIELD,
/***************/
TK__COUNT__
} TokenIndex;
enum TokenValueIndex {
TokenValue_EMPTY = 0,
TokenValue_I64 = 1,
TokenValue_F64 = 2,
TokenValue_STR = 3,
};
typedef struct TokenValue {
enum TokenValueIndex index; // 0: empty
union {
int64_t _i64; // 1
double _f64; // 2
c11_string* _str; // 3
};
} TokenValue;
typedef struct Token {
TokenIndex type;
const char* start;
int length;
int line;
int brackets_level;
TokenValue value;
} Token;
// https://docs.python.org/3/reference/expressions.html#operator-precedence
enum Precedence {
PREC_LOWEST = 0,
PREC_LAMBDA, // lambda
PREC_TERNARY, // ?:
PREC_LOGICAL_OR, // or
PREC_LOGICAL_AND, // and
PREC_LOGICAL_NOT, // not
/* https://docs.python.org/3/reference/expressions.html#comparisons
* Unlike C, all comparison operations in Python have the same priority,
* which is lower than that of any arithmetic, shifting or bitwise operation.
* Also unlike C, expressions like a < b < c have the interpretation that is conventional in
* mathematics.
*/
PREC_COMPARISION, // < > <= >= != ==, in / is / is not / not in
PREC_BITWISE_OR, // |
PREC_BITWISE_XOR, // ^
PREC_BITWISE_AND, // &
PREC_BITWISE_SHIFT, // << >>
PREC_TERM, // + -
PREC_FACTOR, // * / % // @
PREC_UNARY, // - not ~
PREC_EXPONENT, // **
PREC_PRIMARY, // f() x[] a.b 1:2
PREC_HIGHEST,
};
Error* Lexer__process(SourceData_ src, Token** out_tokens, int* out_length);
#define Token__sv(self) \
(c11_sv) { (self)->start, (self)->length }
// compiler/compiler.h
Error* pk_compile(SourceData_ src, CodeObject* out);
// objects/exception.h
typedef struct BaseExceptionFrame {
SourceData_ src;
int lineno;
c11_string* name;
py_TValue locals; // for debugger only
py_TValue globals; // for debugger only
} BaseExceptionFrame;
typedef struct BaseException {
py_TValue args;
py_TValue inner_exc;
c11_vector /*T=BaseExceptionFrame*/ stacktrace;
} BaseException;
char* safe_stringify_exception(py_Ref exc);
char* formatexc_internal(py_Ref exc);
// src/bindings\py_array.c
int pk_arrayview(py_Ref self, py_TValue** p) {
if(self->type == tp_list) {
*p = py_list_data(self);
return py_list_len(self);
}
if(self->type == tp_tuple) {
*p = PyObject__slots(self->_obj);
return py_tuple_len(self);
}
return -1;
}
bool pk_wrapper__arrayequal(py_Type type, int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(!py_istype(py_arg(1), type)) {
py_newnotimplemented(py_retval());
return true;
}
py_TValue *p0, *p1;
int lhs_length = pk_arrayview(py_arg(0), &p0);
int rhs_length = pk_arrayview(py_arg(1), &p1);
assert(lhs_length != -1 && rhs_length != -1);
if(lhs_length != rhs_length) {
py_newbool(py_retval(), false);
return true;
}
for(int i = 0; i < lhs_length; i++) {
int res = py_equal(p0 + i, p1 + i);
if(res == -1) return false;
if(!res) {
py_newbool(py_retval(), false);
return true;
}
}
py_newbool(py_retval(), true);
return true;
}
bool pk_arraycontains(py_Ref self, py_Ref val) {
py_TValue* p;
int length = pk_arrayview(self, &p);
if(length == -1) return TypeError("expected list or tuple, got %t", self->type);
for(int i = 0; i < length; i++) {
int res = py_equal(p + i, val);
if(res == -1) return false;
if(res) {
py_newbool(py_retval(), true);
return true;
}
}
py_newbool(py_retval(), false);
return true;
}
bool list_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
list_iterator* ud = py_touserdata(argv);
if(ud->index < ud->vec->length) {
py_TValue* res = c11__at(py_TValue, ud->vec, ud->index);
py_assign(py_retval(), res);
ud->index++;
return true;
}
return StopIteration();
}
bool tuple_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
tuple_iterator* ud = py_touserdata(argv);
if(ud->index < ud->length) {
py_assign(py_retval(), ud->p + ud->index);
ud->index++;
return true;
}
return StopIteration();
}
py_Type pk_list_iterator__register() {
py_Type type = pk_newtype("list_iterator", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, list_iterator__next__);
return type;
}
py_Type pk_tuple_iterator__register() {
py_Type type = pk_newtype("tuple_iterator", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, tuple_iterator__next__);
return type;
}
// src/bindings\py_mappingproxy.c
#include <stdbool.h>
void pk_mappingproxy__namedict(py_Ref out, py_Ref object) {
py_newobject(out, tp_namedict, 1, 0);
assert(object->is_ptr && object->_obj->slots == -1);
py_setslot(out, 0, object);
}
static bool namedict__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = py_getdict(py_getslot(argv, 0), name);
if(!res) return KeyError(py_arg(1));
py_assign(py_retval(), res);
return true;
}
static bool namedict__get(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = py_getdict(py_getslot(argv, 0), name);
py_assign(py_retval(), res ? res : py_arg(2));
return true;
}
static bool namedict__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_setdict(py_getslot(argv, 0), name, py_arg(2));
py_newnone(py_retval());
return true;
}
static bool namedict__delitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
if(!py_deldict(py_getslot(argv, 0), name)) return KeyError(py_arg(1));
py_newnone(py_retval());
return true;
}
static bool namedict__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_Ref res = py_getdict(py_getslot(argv, 0), name);
py_newbool(py_retval(), res != NULL);
return true;
}
static bool namedict_items(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref object = py_getslot(argv, 0);
NameDict* dict = PyObject__dict(object->_obj);
py_newlist(py_retval());
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
py_Ref slot = py_list_emplace(py_retval());
py_Ref p = py_newtuple(slot, 2);
p[0] = *py_name2ref(kv->key);
p[1] = kv->value;
}
return true;
}
static bool namedict_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref object = py_getslot(argv, 0);
NameDict* dict = PyObject__dict(object->_obj);
NameDict__clear(dict);
py_newnone(py_retval());
return true;
}
py_Type pk_namedict__register() {
py_Type type = pk_newtype("namedict", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __getitem__, namedict__getitem__);
py_bindmagic(type, __setitem__, namedict__setitem__);
py_bindmagic(type, __delitem__, namedict__delitem__);
py_bindmagic(type, __contains__, namedict__contains__);
py_setdict(py_tpobject(type), __hash__, py_None());
py_bindmethod(type, "items", namedict_items);
py_bindmethod(type, "clear", namedict_clear);
py_bindmethod(type, "get", namedict__get);
return type;
}
// src/bindings\py_method.c
/* staticmethod */
static bool staticmethod__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_newobject(py_retval(), tp_staticmethod, 1, 0);
py_setslot(py_retval(), 0, py_arg(1));
return true;
}
py_Type pk_staticmethod__register() {
py_Type type = pk_newtype("staticmethod", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, staticmethod__new__);
return type;
}
/* classmethod */
static bool classmethod__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_newobject(py_retval(), tp_classmethod, 1, 0);
py_setslot(py_retval(), 0, py_arg(1));
return true;
}
py_Type pk_classmethod__register() {
py_Type type = pk_newtype("classmethod", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, classmethod__new__);
return type;
}
/* boundmethod */
static bool boundmethod__self__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), py_getslot(argv, 0));
return true;
}
static bool boundmethod__func__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), py_getslot(argv, 1));
return true;
}
static bool boundmethod__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(!py_istype(py_arg(1), tp_boundmethod)) {
py_newbool(py_retval(), false);
return true;
}
for(int i = 0; i < 2; i++) {
int res = py_equal(py_getslot(&argv[0], i), py_getslot(&argv[1], i));
if(res == -1) return false;
if(!res) {
py_newbool(py_retval(), false);
return true;
}
}
py_newbool(py_retval(), true);
return true;
}
static bool boundmethod__ne__(int argc, py_Ref argv) {
bool ok = boundmethod__eq__(argc, argv);
if(!ok) return false;
bool res = py_tobool(py_retval());
py_newbool(py_retval(), !res);
return true;
}
py_Type pk_boundmethod__register() {
py_Type type = pk_newtype("boundmethod", tp_object, NULL, NULL, false, true);
py_bindproperty(type, "__self__", boundmethod__self__, NULL);
py_bindproperty(type, "__func__", boundmethod__func__, NULL);
py_bindmagic(type, __eq__, boundmethod__eq__);
py_bindmagic(type, __ne__, boundmethod__ne__);
return type;
}
// src/bindings\py_number.c
static bool try_castfloat(py_Ref self, double* out) {
switch(self->type) {
case tp_int: *out = (double)self->_i64; return true;
case tp_float: *out = self->_f64; return true;
default: return false;
}
}
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \
static bool int##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
if(py_isint(&argv[1])) { \
py_i64 lhs = py_toint(&argv[0]); \
py_i64 rhs = py_toint(&argv[1]); \
rint(py_retval(), lhs op rhs); \
} else if(py_isfloat(&argv[1])) { \
py_i64 lhs = py_toint(&argv[0]); \
py_f64 rhs = py_tofloat(&argv[1]); \
rfloat(py_retval(), lhs op rhs); \
} else { \
py_newnotimplemented(py_retval()); \
} \
return true; \
} \
static bool float##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
py_f64 lhs = py_tofloat(&argv[0]); \
py_f64 rhs; \
if(try_castfloat(&argv[1], &rhs)) { \
rfloat(py_retval(), lhs op rhs); \
} else { \
py_newnotimplemented(py_retval()); \
} \
return true; \
}
DEF_NUM_BINARY_OP(__add__, +, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__sub__, -, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__mul__, *, py_newint, py_newfloat)
DEF_NUM_BINARY_OP(__eq__, ==, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__ne__, !=, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__lt__, <, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__le__, <=, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
static bool int__neg__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), -val);
return true;
}
static bool float__neg__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]);
py_newfloat(py_retval(), -val);
return true;
}
static bool int__truediv__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]);
py_f64 rhs;
if(try_castfloat(&argv[1], &rhs)) {
if(rhs == 0.0) return ZeroDivisionError("float division by zero");
py_newfloat(py_retval(), lhs / rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool float__truediv__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 lhs = py_tofloat(&argv[0]);
py_f64 rhs;
if(try_castfloat(&argv[1], &rhs)) {
if(rhs == 0.0) return ZeroDivisionError("float division by zero");
py_newfloat(py_retval(), lhs / rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool number__pow__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
py_i64 lhs = py_toint(&argv[0]);
py_i64 rhs = py_toint(&argv[1]);
if(rhs < 0) {
if(lhs == 0) {
return ZeroDivisionError("0.0 cannot be raised to a negative power");
} else {
py_newfloat(py_retval(), dmath_pow(lhs, rhs));
}
} else {
// rhs >= 0
py_i64 ret = 1;
while(true) {
if(rhs & 1) ret *= lhs;
rhs >>= 1;
if(!rhs) break;
lhs *= lhs; // place this here to avoid overflow
}
py_newint(py_retval(), ret);
}
} else {
py_f64 lhs, rhs;
if(!py_castfloat(&argv[0], &lhs)) return false;
if(try_castfloat(&argv[1], &rhs)) {
py_newfloat(py_retval(), dmath_pow(lhs, rhs));
} else {
py_newnotimplemented(py_retval());
}
}
return true;
}
static py_i64 i64_abs(py_i64 x) { return x < 0 ? -x : x; }
static py_i64 cpy11__fast_floor_div(py_i64 a, py_i64 b) {
assert(b != 0);
if(a == 0) return 0;
if((a < 0) == (b < 0)) {
return i64_abs(a) / i64_abs(b);
} else {
return -1 - (i64_abs(a) - 1) / i64_abs(b);
}
}
static py_i64 cpy11__fast_mod(py_i64 a, py_i64 b) {
assert(b != 0);
if(a == 0) return 0;
py_i64 res;
if((a < 0) == (b < 0)) {
res = i64_abs(a) % i64_abs(b);
} else {
res = i64_abs(b) - 1 - (i64_abs(a) - 1) % i64_abs(b);
}
return b < 0 ? -res : res;
}
// https://github.com/python/cpython/blob/3.11/Objects/floatobject.c#L677
static void cpy11__float_div_mod(double vx, double wx, double *floordiv, double *mod)
{
double div;
*mod = dmath_fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathematically* an
exact multiple of wx. But this is fp arithmetic, and fp
vx - mod is an approximation; the result is that div may
not be an exact integral value after the division, although
it will always be very close to one.
*/
div = (vx - *mod) / wx;
if (*mod) {
/* ensure the remainder has the same sign as the denominator */
if ((wx < 0) != (*mod < 0)) {
*mod += wx;
div -= 1.0;
}
}
else {
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
it has the same sign as the denominator. */
*mod = dmath_copysign(0.0, wx);
}
/* snap quotient to nearest integral value */
if (div) {
*floordiv = dmath_floor(div);
if (div - *floordiv > 0.5) {
*floordiv += 1.0;
}
}
else {
/* div is zero - get the same sign as the true quotient */
*floordiv = dmath_copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
}
}
static bool int__floordiv__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) {
py_i64 rhs = py_toint(&argv[1]);
if(rhs == 0) return ZeroDivisionError("integer division by zero");
py_newint(py_retval(), cpy11__fast_floor_div(lhs, rhs));
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool int__mod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) {
py_i64 rhs = py_toint(&argv[1]);
if(rhs == 0) return ZeroDivisionError("integer modulo by zero");
py_newint(py_retval(), cpy11__fast_mod(lhs, rhs));
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool float__floordiv__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 lhs = py_tofloat(&argv[0]);
py_f64 rhs;
if(try_castfloat(&argv[1], &rhs)) {
if(rhs == 0.0) return ZeroDivisionError("float modulo by zero");
double q, r;
cpy11__float_div_mod(lhs, rhs, &q, &r);
py_newfloat(py_retval(), q);
return true;
}
py_newnotimplemented(py_retval());
return true;
}
static bool float__rfloordiv__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 rhs = py_tofloat(&argv[0]);
py_f64 lhs;
if(try_castfloat(&argv[1], &lhs)) {
if(rhs == 0.0) return ZeroDivisionError("float modulo by zero");
double q, r;
cpy11__float_div_mod(lhs, rhs, &q, &r);
py_newfloat(py_retval(), q);
return true;
}
py_newnotimplemented(py_retval());
return true;
}
static bool float__mod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 lhs = py_tofloat(&argv[0]);
py_f64 rhs;
if(try_castfloat(&argv[1], &rhs)) {
if(rhs == 0.0) return ZeroDivisionError("float modulo by zero");
double q, r;
cpy11__float_div_mod(lhs, rhs, &q, &r);
py_newfloat(py_retval(), r);
return true;
}
py_newnotimplemented(py_retval());
return true;
}
static bool float__rmod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 rhs = py_tofloat(&argv[0]);
py_f64 lhs;
if(try_castfloat(&argv[1], &lhs)) {
if(rhs == 0.0) return ZeroDivisionError("float modulo by zero");
double q, r;
cpy11__float_div_mod(lhs, rhs, &q, &r);
py_newfloat(py_retval(), r);
return true;
}
py_newnotimplemented(py_retval());
return true;
}
static bool float__divmod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 lhs = py_tofloat(&argv[0]);
py_f64 rhs;
if(try_castfloat(&argv[1], &rhs)) {
if(rhs == 0.0) return ZeroDivisionError("float modulo by zero");
double q, r;
cpy11__float_div_mod(lhs, rhs, &q, &r);
py_Ref p = py_newtuple(py_retval(), 2);
py_newfloat(&p[0], q);
py_newfloat(&p[1], r);
return true;
}
return TypeError("divmod() expects int or float as divisor");
}
static bool int__divmod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_int);
py_i64 lhs = py_toint(&argv[0]);
py_i64 rhs = py_toint(&argv[1]);
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
py_Ref p = py_newtuple(py_retval(), 2);
py_newint(&p[0], cpy11__fast_floor_div(lhs, rhs));
py_newint(&p[1], cpy11__fast_mod(lhs, rhs));
return true;
}
static bool int__invert__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), ~val);
return true;
}
static bool int_bit_length(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 x = py_toint(py_arg(0));
if(x < 0) x = -x;
int bits = 0;
while(x) {
x >>= 1;
bits++;
}
py_newint(py_retval(), bits);
return true;
}
#define DEF_INT_BITWISE_OP(name, op) \
static bool int##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
py_i64 lhs = py_toint(&argv[0]); \
if(py_isint(&argv[1])) { \
py_i64 rhs = py_toint(&argv[1]); \
py_newint(py_retval(), lhs op rhs); \
} else { \
py_newnotimplemented(py_retval()); \
} \
return true; \
}
DEF_INT_BITWISE_OP(__and__, &)
DEF_INT_BITWISE_OP(__or__, |)
DEF_INT_BITWISE_OP(__xor__, ^)
DEF_INT_BITWISE_OP(__lshift__, <<)
DEF_INT_BITWISE_OP(__rshift__, >>)
static bool int__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]);
char buf[32];
int size = snprintf(buf, sizeof(buf), "%lld", (long long)val);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
static bool float__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_f64(&buf, val, -1);
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool int__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), argv);
return true;
}
static bool float__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]);
py_i64 h_user;
memcpy(&h_user, &val, sizeof(py_f64));
py_newint(py_retval(), h_user);
return true;
}
static bool int__abs__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), val < 0 ? -val : val);
return true;
}
static bool float__abs__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]);
py_newfloat(py_retval(), val < 0 ? -val : val);
return true;
}
static bool int__new__(int argc, py_Ref argv) {
if(argc == 1 + 0) {
// int() == 0
py_newint(py_retval(), 0);
return true;
}
// 1 arg
if(argc == 1 + 1) {
switch(argv[1].type) {
case tp_float: {
// int(1.1) == 1
py_newint(py_retval(), (py_i64)py_tofloat(&argv[1]));
return true;
}
case tp_int: {
// int(1) == 1
*py_retval() = argv[1];
return true;
}
case tp_bool: {
// int(True) == 1
py_newint(py_retval(), (py_i64)py_tobool(&argv[1]));
return true;
}
case tp_str: break; // leave to the next block
default: return TypeError("int() argument must be a string, number or boolean");
}
}
// 2+ args -> error
if(argc > 1 + 2) return TypeError("int() takes at most 2 arguments");
// 1 or 2 args with str
int base = 10;
if(argc == 1 + 2) {
PY_CHECK_ARG_TYPE(2, tp_int);
base = py_toint(py_arg(2));
}
PY_CHECK_ARG_TYPE(1, tp_str);
c11_sv sv = py_tosv(py_arg(1));
bool negative = false;
if(sv.size && (sv.data[0] == '+' || sv.data[0] == '-')) {
negative = sv.data[0] == '-';
sv.data++;
sv.size--;
}
py_i64 val;
if(c11__parse_uint(sv, &val, base) != IntParsing_SUCCESS) {
return ValueError("invalid literal for int() with base %d: %q", base, sv);
}
py_newint(py_retval(), negative ? -val : val);
return true;
}
static bool float__new__(int argc, py_Ref argv) {
if(argc == 1 + 0) {
// float() == 0.0
py_newfloat(py_retval(), 0.0);
return true;
}
if(argc > 1 + 1) return TypeError("float() takes at most 1 argument");
// 1 arg
switch(argv[1].type) {
case tp_int: {
// float(1) == 1.0
py_newfloat(py_retval(), py_toint(&argv[1]));
return true;
}
case tp_float: {
// float(1.1) == 1.1
*py_retval() = argv[1];
return true;
}
case tp_bool: {
// float(True) == 1.0
py_newfloat(py_retval(), py_tobool(&argv[1]));
return true;
}
case tp_str: {
// str to float
c11_sv sv = py_tosv(py_arg(1));
if(c11__sveq2(sv, "inf")) {
py_newfloat(py_retval(), DMATH_INFINITY);
return true;
}
if(c11__sveq2(sv, "-inf")) {
py_newfloat(py_retval(), -DMATH_INFINITY);
return true;
}
char* p_end;
py_f64 float_out = strtod(sv.data, &p_end);
if(p_end != sv.data + sv.size) return ValueError("invalid literal for float(): %q", sv);
py_newfloat(py_retval(), float_out);
return true;
}
default: return TypeError("float() argument must be a string or a real number");
}
}
// tp_bool
static bool bool__new__(int argc, py_Ref argv) {
assert(argc > 0);
if(argc == 1) {
py_newbool(py_retval(), false);
return true;
}
if(argc == 2) {
int res = py_bool(py_arg(1));
if(res == -1) return false;
py_newbool(py_retval(), res);
return true;
}
return TypeError("bool() takes at most 1 argument");
}
static bool bool__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
bool res = py_tobool(argv);
py_newint(py_retval(), res);
return true;
}
static bool bool__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
bool res = py_tobool(argv);
py_newstr(py_retval(), res ? "True" : "False");
return true;
}
static bool bool__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool) {
bool rhs = py_tobool(&argv[1]);
py_newbool(py_retval(), lhs == rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool bool__ne__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool) {
bool rhs = py_tobool(&argv[1]);
py_newbool(py_retval(), lhs != rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
#define DEF_BOOL_BITWISE(name, op) \
static bool bool##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
bool lhs = py_tobool(&argv[0]); \
if(argv[1].type == tp_bool) { \
bool rhs = py_tobool(&argv[1]); \
py_newbool(py_retval(), lhs op rhs); \
} else { \
py_newnotimplemented(py_retval()); \
} \
return true; \
}
DEF_BOOL_BITWISE(__and__, &&)
DEF_BOOL_BITWISE(__or__, ||)
DEF_BOOL_BITWISE(__xor__, !=)
static bool bool__invert__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
bool val = py_tobool(&argv[0]);
py_newbool(py_retval(), !val);
return true;
}
static bool bool_try_cast_i64(py_Ref arg, py_i64* out) {
if (arg->type == tp_int) {
*out = py_toint(arg);
return true;
} else if (arg->type == tp_bool) {
*out = py_tobool(arg);
return true;
} else {
return false;
}
}
static bool bool__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_tobool(py_arg(0));
py_i64 rhs;
if (bool_try_cast_i64(py_arg(1), &rhs)) {
py_newint(py_retval(), lhs + rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool bool__sub__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_tobool(py_arg(0));
py_i64 rhs;
if (bool_try_cast_i64(py_arg(1), &rhs)) {
py_newint(py_retval(), lhs - rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool bool__rsub__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_tobool(py_arg(0));
py_i64 rhs;
if (bool_try_cast_i64(py_arg(1), &rhs)) {
py_newint(py_retval(), rhs - lhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool bool__mul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_i64 lhs = py_tobool(py_arg(0));
py_i64 rhs;
if (bool_try_cast_i64(py_arg(1), &rhs)) {
py_newint(py_retval(), lhs * rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
void pk_number__register() {
/****** tp_int & tp_float ******/
py_bindmagic(tp_int, __add__, int__add__);
py_bindmagic(tp_float, __add__, float__add__);
py_bindmagic(tp_int, __sub__, int__sub__);
py_bindmagic(tp_float, __sub__, float__sub__);
py_bindmagic(tp_int, __mul__, int__mul__);
py_bindmagic(tp_float, __mul__, float__mul__);
py_bindmagic(tp_int, __eq__, int__eq__);
py_bindmagic(tp_float, __eq__, float__eq__);
py_bindmagic(tp_int, __ne__, int__ne__);
py_bindmagic(tp_float, __ne__, float__ne__);
py_bindmagic(tp_int, __lt__, int__lt__);
py_bindmagic(tp_float, __lt__, float__lt__);
py_bindmagic(tp_int, __le__, int__le__);
py_bindmagic(tp_float, __le__, float__le__);
py_bindmagic(tp_int, __gt__, int__gt__);
py_bindmagic(tp_float, __gt__, float__gt__);
py_bindmagic(tp_int, __ge__, int__ge__);
py_bindmagic(tp_float, __ge__, float__ge__);
// __neg__
py_bindmagic(tp_int, __neg__, int__neg__);
py_bindmagic(tp_float, __neg__, float__neg__);
// __repr__
py_bindmagic(tp_int, __repr__, int__repr__);
py_bindmagic(tp_float, __repr__, float__repr__);
// __hash__
py_bindmagic(tp_int, __hash__, int__hash__);
py_bindmagic(tp_float, __hash__, float__hash__);
// __abs__
py_bindmagic(tp_int, __abs__, int__abs__);
py_bindmagic(tp_float, __abs__, float__abs__);
// __new__
py_bindmagic(tp_int, __new__, int__new__);
py_bindmagic(tp_float, __new__, float__new__);
// __truediv__
py_bindmagic(tp_int, __truediv__, int__truediv__);
py_bindmagic(tp_float, __truediv__, float__truediv__);
// __pow__
py_bindmagic(tp_int, __pow__, number__pow__);
py_bindmagic(tp_float, __pow__, number__pow__);
// __floordiv__ & __mod__ & __divmod__
py_bindmagic(tp_int, __floordiv__, int__floordiv__);
py_bindmagic(tp_int, __mod__, int__mod__);
py_bindmagic(tp_int, __divmod__, int__divmod__);
// fmod
py_bindmagic(tp_float, __floordiv__, float__floordiv__);
py_bindmagic(tp_float, __rfloordiv__, float__rfloordiv__);
py_bindmagic(tp_float, __mod__, float__mod__);
py_bindmagic(tp_float, __rmod__, float__rmod__);
py_bindmagic(tp_float, __divmod__, float__divmod__);
// int.__invert__ & int.<BITWISE OP>
py_bindmagic(tp_int, __invert__, int__invert__);
py_bindmagic(tp_int, __and__, int__and__);
py_bindmagic(tp_int, __or__, int__or__);
py_bindmagic(tp_int, __xor__, int__xor__);
py_bindmagic(tp_int, __lshift__, int__lshift__);
py_bindmagic(tp_int, __rshift__, int__rshift__);
// int.bit_length
py_bindmethod(tp_int, "bit_length", int_bit_length);
/* tp_bool */
py_bindmagic(tp_bool, __new__, bool__new__);
py_bindmagic(tp_bool, __hash__, bool__hash__);
py_bindmagic(tp_bool, __repr__, bool__repr__);
py_bindmagic(tp_bool, __eq__, bool__eq__);
py_bindmagic(tp_bool, __ne__, bool__ne__);
py_bindmagic(tp_bool, __and__, bool__and__);
py_bindmagic(tp_bool, __or__, bool__or__);
py_bindmagic(tp_bool, __xor__, bool__xor__);
py_bindmagic(tp_bool, __invert__, bool__invert__);
py_bindmagic(tp_bool, __add__, bool__add__);
py_bindmagic(tp_bool, __sub__, bool__sub__);
py_bindmagic(tp_bool, __mul__, bool__mul__);
py_bindmagic(tp_bool, __radd__, bool__add__);
py_bindmagic(tp_bool, __rsub__, bool__rsub__);
py_bindmagic(tp_bool, __rmul__, bool__mul__);
}
#undef DEF_NUM_BINARY_OP
#undef DEF_INT_BITWISE_OP
#undef DEF_BOOL_BITWISE
// src/bindings\py_object.c
bool pk__object_new(int argc, py_Ref argv) {
if(argc == 0) return TypeError("object.__new__(): not enough arguments");
py_TypeInfo* ti = py_touserdata(argv);
py_Type cls = ti->index;
if(!ti->is_python) {
return TypeError("object.__new__(%t) is not safe, use %t.__new__() instead", cls, cls);
}
py_newobject(py_retval(), cls, -1, 0);
return true;
}
static bool object__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
assert(argv->is_ptr);
py_newint(py_retval(), (intptr_t)argv->_obj);
return true;
}
static bool object__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
bool res = py_isidentical(py_arg(0), py_arg(1));
py_newbool(py_retval(), res);
return true;
}
static bool object__ne__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
bool res = py_isidentical(py_arg(0), py_arg(1));
py_newbool(py_retval(), !res);
return true;
}
static bool object__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
assert(argv->is_ptr);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "<%t object at %p>", argv->type, argv->_obj);
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool object__dict__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(argv->is_ptr && argv->_obj->slots == -1) {
pk_mappingproxy__namedict(py_retval(), argv);
} else {
py_newnone(py_retval());
}
return true;
}
static bool type__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "<class '%t'>", py_totype(argv));
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool type__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_Type type = py_typeof(py_arg(1));
py_assign(py_retval(), py_tpobject(type));
return true;
}
static bool type__base__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_TypeInfo* ti = py_touserdata(argv);
if(ti->base) {
py_assign(py_retval(), &ti->base_ti->self);
} else {
py_newnone(py_retval());
}
return true;
}
static bool type__name__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_TypeInfo* ti = py_touserdata(argv);
py_assign(py_retval(), py_name2ref(ti->name));
return true;
}
static bool type__getitem__(int argc, py_Ref argv) {
py_assign(py_retval(), argv);
return true;
}
static bool type__or__(int argc, py_Ref argv) {
py_assign(py_retval(), argv);
return true;
}
static bool type__module__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_TypeInfo* ti = py_touserdata(argv);
if(py_isnil(ti->module)) {
py_newnone(py_retval());
} else {
py_ModuleInfo* mi = py_touserdata(ti->module);
py_newstrv(py_retval(), c11_string__sv(mi->path));
}
return true;
}
static bool type__annotations__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_TypeInfo* ti = py_touserdata(argv);
if(py_isnil(&ti->annotations)) {
py_newdict(py_retval());
} else {
py_assign(py_retval(), &ti->annotations);
}
return true;
}
void pk_object__register() {
py_bindmagic(tp_object, __new__, pk__object_new);
py_bindmagic(tp_object, __hash__, object__hash__);
py_bindmagic(tp_object, __eq__, object__eq__);
py_bindmagic(tp_object, __ne__, object__ne__);
py_bindmagic(tp_object, __repr__, object__repr__);
py_bindmagic(tp_type, __repr__, type__repr__);
py_bindmagic(tp_type, __new__, type__new__);
py_bindmagic(tp_type, __getitem__, type__getitem__);
py_bindmagic(tp_type, __or__, type__or__);
py_bindproperty(tp_type, "__module__", type__module__, NULL);
py_bindproperty(tp_type, "__base__", type__base__, NULL);
py_bindproperty(tp_type, "__name__", type__name__, NULL);
py_bindproperty(tp_object, "__dict__", object__dict__, NULL);
py_bindproperty(tp_type, "__annotations__", type__annotations__, NULL);
}
// src/bindings\py_property.c
static bool property__new__(int argc, py_Ref argv) {
py_newobject(py_retval(), tp_property, 2, 0);
if(argc == 1 + 1) {
py_setslot(py_retval(), 0, py_arg(1));
py_setslot(py_retval(), 1, py_None());
} else if(argc == 1 + 2) {
py_setslot(py_retval(), 0, py_arg(1));
py_setslot(py_retval(), 1, py_arg(2));
} else {
return TypeError("property() expected 1 or 2 arguments, got %d", argc - 1);
}
return true;
}
static bool property_setter(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_setslot(argv, 1, py_arg(1));
py_assign(py_retval(), argv);
return true;
}
static bool property_fget(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref fget = py_getslot(argv, 0);
py_assign(py_retval(), fget);
return true;
}
static bool property_fset(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref fset = py_getslot(argv, 1);
py_assign(py_retval(), fset);
return true;
}
py_Type pk_property__register() {
py_Type type = pk_newtype("property", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, property__new__);
py_bindmethod(type, "setter", property_setter);
py_bindproperty(type, "fget", property_fget, NULL);
py_bindproperty(type, "fset", property_fset, NULL);
return type;
}
// src/bindings\py_range.c
typedef struct Range {
py_i64 start;
py_i64 stop;
py_i64 step;
} Range;
static bool range__new__(int argc, py_Ref argv) {
Range* ud = py_newobject(py_retval(), tp_range, 0, sizeof(Range));
switch(argc - 1) { // skip cls
case 1: {
PY_CHECK_ARG_TYPE(1, tp_int);
ud->start = 0;
ud->stop = py_toint(py_arg(1));
ud->step = 1;
break;
}
case 2:
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
ud->start = py_toint(py_arg(1));
ud->stop = py_toint(py_arg(2));
ud->step = 1;
break;
case 3:
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
PY_CHECK_ARG_TYPE(3, tp_int);
ud->start = py_toint(py_arg(1));
ud->stop = py_toint(py_arg(2));
ud->step = py_toint(py_arg(3));
break;
default: return TypeError("range() expected at most 3 arguments, got %d", argc - 1);
}
if(ud->step == 0) return ValueError("range() step must not be zero");
return true;
}
static bool range__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_tpcall(tp_range_iterator, 1, argv);
}
py_Type pk_range__register() {
py_Type type = pk_newtype("range", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, range__new__);
py_bindmagic(type, __iter__, range__iter__);
return type;
}
typedef struct RangeIterator {
Range range;
py_i64 current;
} RangeIterator;
static bool range_iterator__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_range);
RangeIterator* ud = py_newobject(py_retval(), tp_range_iterator, 0, sizeof(RangeIterator));
ud->range = *(Range*)py_touserdata(py_arg(1));
ud->current = ud->range.start;
return true;
}
bool range_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
RangeIterator* ud = py_touserdata(argv);
if(ud->range.step > 0) {
if(ud->current >= ud->range.stop) return StopIteration();
} else {
if(ud->current <= ud->range.stop) return StopIteration();
}
py_newint(py_retval(), ud->current);
ud->current += ud->range.step;
return true;
}
py_Type pk_range_iterator__register() {
py_Type type = pk_newtype("range_iterator", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, range_iterator__new__);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, range_iterator__next__);
return type;
}
// src/bindings\py_str.c
#include <stdbool.h>
c11_string* pk_tostr(py_Ref self) {
assert(self->type == tp_str);
if(!self->is_ptr) {
return (c11_string*)(&self->extra);
} else {
return PyObject__userdata(self->_obj);
}
}
////////////////////////////////
static bool str__new__(int argc, py_Ref argv) {
assert(argc >= 1);
if(argc == 1) {
py_newstr(py_retval(), "");
return true;
}
if(argc > 2) return TypeError("str() takes at most 1 argument");
return py_str(py_arg(1));
}
static bool str__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
uint64_t res = c11_sv__hash(py_tosv(argv));
py_newint(py_retval(), (py_i64)res);
return true;
}
static bool str__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]);
py_newint(py_retval(), c11_sv__u8_length((c11_sv){self->data, self->size}));
return true;
}
static bool str__mod__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
// %s
// %d %i
// %f
// %r
// %%
py_TValue* args;
int args_count;
if(py_istype(&argv[1], tp_tuple)) {
args_count = py_tuple_len(&argv[1]);
args = py_tuple_data(&argv[1]);
} else {
args_count = 1;
args = &argv[1];
}
int arg_index = 0;
const char* p = self->data;
const char* p_end = self->data + self->size;
c11_sbuf buf;
c11_sbuf__ctor(&buf);
while(p < p_end) {
if(*p == '%') {
p++;
if(p >= p_end) {
c11_sbuf__dtor(&buf);
return ValueError("incomplete format");
}
char spec = *p;
p++;
if(spec == '%') {
// %% -> %
c11_sbuf__write_char(&buf, '%');
} else if(spec == 's') {
// %s -> string
if(arg_index >= args_count) {
c11_sbuf__dtor(&buf);
return TypeError("not enough arguments for format string");
}
if(!py_str(&args[arg_index])) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
arg_index++;
} else if(spec == 'd' || spec == 'i') {
// %d or %i -> integer
if(arg_index >= args_count) {
c11_sbuf__dtor(&buf);
return TypeError("not enough arguments for format string");
}
if(!py_checktype(&args[arg_index], tp_int)) {
c11_sbuf__dtor(&buf);
return false;
}
py_i64 val = py_toint(&args[arg_index]);
c11_sbuf__write_i64(&buf, val);
arg_index++;
} else if(spec == 'f') {
// %f -> float
if(arg_index >= args_count) {
c11_sbuf__dtor(&buf);
return TypeError("not enough arguments for format string");
}
py_f64 val;
if(py_istype(&args[arg_index], tp_float)) {
val = py_tofloat(&args[arg_index]);
} else if(py_istype(&args[arg_index], tp_int)) {
val = (py_f64)py_toint(&args[arg_index]);
} else {
c11_sbuf__dtor(&buf);
return TypeError("a float is required");
}
c11_sbuf__write_f64(&buf, val, 6);
arg_index++;
} else if(spec == 'r') {
// %r -> repr
if(arg_index >= args_count) {
c11_sbuf__dtor(&buf);
return TypeError("not enough arguments for format string");
}
if(!py_repr(&args[arg_index])) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
arg_index++;
} else {
c11_sbuf__dtor(&buf);
return ValueError("unsupported format character '%c'", spec);
}
} else {
c11_sbuf__write_char(&buf, *p);
p++;
}
}
if(arg_index != args_count) {
c11_sbuf__dtor(&buf);
return TypeError("not all arguments converted during string formatting");
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool str__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval());
} else {
c11_string* other = pk_tostr(&argv[1]);
char* p = py_newstrn(py_retval(), self->size + other->size);
memcpy(p, self->data, self->size);
memcpy(p + self->size, other->data, other->size);
}
return true;
}
static bool str__mul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
if(py_arg(1)->type != tp_int) {
py_newnotimplemented(py_retval());
} else {
py_i64 n = py_toint(py_arg(1));
if(n <= 0) {
py_newstr(py_retval(), "");
} else {
char* p = py_newstrn(py_retval(), self->size * n);
for(int i = 0; i < n; i++) {
memcpy(p + i * self->size, self->data, self->size);
}
}
}
return true;
}
static bool str__rmul__(int argc, py_Ref argv) { return str__mul__(argc, argv); }
static bool str__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval());
} else {
c11_string* other = pk_tostr(&argv[1]);
const char* p = strstr(self->data, other->data);
py_newbool(py_retval(), p != NULL);
}
return true;
}
static bool str__str__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
*py_retval() = argv[0];
return true;
}
static bool str__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_quoted(&buf, py_tosv(&argv[0]), '\'');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool str__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int* ud = py_newobject(py_retval(), tp_str_iterator, 1, sizeof(int));
*ud = 0;
py_setslot(py_retval(), 0, argv); // keep a reference to the string
return true;
}
static bool str__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(&argv[0]));
py_Ref _1 = py_arg(1);
if(_1->type == tp_int) {
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self.size)) return false;
c11_sv res = c11_sv__u8_getitem(self, index);
py_newstrv(py_retval(), res);
return true;
} else if(_1->type == tp_slice) {
int start, stop, step;
bool ok = pk__parse_int_slice(_1, c11_sv__u8_length(self), &start, &stop, &step);
if(!ok) return false;
c11_string* res = c11_sv__u8_slice(self, start, stop, step);
py_newstrv(py_retval(), (c11_sv){res->data, res->size});
c11_string__delete(res);
return true;
} else {
return TypeError("string indices must be integers");
}
}
#define DEF_STR_CMP_OP(op, __f, __cond) \
static bool str##op(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
c11_string* self = pk_tostr(&argv[0]); \
if(py_arg(1)->type != tp_str) { \
py_newnotimplemented(py_retval()); \
} else { \
c11_string* other = pk_tostr(&argv[1]); \
int res = __f(c11_string__sv(self), c11_string__sv(other)); \
py_newbool(py_retval(), __cond); \
} \
return true; \
}
DEF_STR_CMP_OP(__eq__, c11__sveq, res)
DEF_STR_CMP_OP(__ne__, c11__sveq, !res)
DEF_STR_CMP_OP(__lt__, c11_sv__cmp, res < 0)
DEF_STR_CMP_OP(__le__, c11_sv__cmp, res <= 0)
DEF_STR_CMP_OP(__gt__, c11_sv__cmp, res > 0)
DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
#undef DEF_STR_CMP_OP
static bool str_lower(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]);
char* p = py_newstrn(py_retval(), self->size);
for(int i = 0; i < self->size; i++) {
char c = self->data[i];
p[i] = c >= 'A' && c <= 'Z' ? c + 32 : c;
}
return true;
}
static bool str_upper(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = pk_tostr(&argv[0]);
char* p = py_newstrn(py_retval(), self->size);
for(int i = 0; i < self->size; i++) {
char c = self->data[i];
p[i] = c >= 'a' && c <= 'z' ? c - 32 : c;
}
return true;
}
static bool str_startswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = pk_tostr(&argv[1]);
py_newbool(py_retval(), c11_sv__startswith(c11_string__sv(self), c11_string__sv(other)));
return true;
}
static bool str_endswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = pk_tostr(&argv[1]);
py_newbool(py_retval(), c11_sv__endswith(c11_string__sv(self), c11_string__sv(other)));
return true;
}
static bool str_join(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(argv));
if(!py_iter(py_arg(1))) return false;
py_push(py_retval()); // iter
c11_sbuf buf;
c11_sbuf__ctor(&buf);
bool first = true;
while(true) {
int res = py_next(py_peek(-1));
if(res == -1) {
c11_sbuf__dtor(&buf);
return false;
}
if(res == 0) break;
if(!first) c11_sbuf__write_sv(&buf, self);
if(!py_checkstr(py_retval())) {
c11_sbuf__dtor(&buf);
return false;
}
c11_string* item = pk_tostr(py_retval());
c11_sbuf__write_cstrn(&buf, item->data, item->size);
first = false;
}
py_pop(); // iter
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool str_replace(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
c11_string* self = pk_tostr(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_str);
c11_string* old = pk_tostr(&argv[1]);
c11_string* new_ = pk_tostr(&argv[2]);
c11_string* res =
c11_sv__replace2(c11_string__sv(self), c11_string__sv(old), c11_string__sv(new_));
py_newstrv(py_retval(), (c11_sv){res->data, res->size});
c11_string__delete(res);
return true;
}
static bool str_split(int argc, py_Ref argv) {
c11_sv self = c11_string__sv(pk_tostr(&argv[0]));
c11_vector res;
bool discard_empty = false;
if(argc > 2) return TypeError("split() takes at most 2 arguments");
if(argc == 1) {
// sep = None
res = c11_sv__splitwhitespace(self);
discard_empty = true;
}
if(argc == 2) {
// sep = argv[1]
if(!py_checkstr(&argv[1])) return false;
c11_sv sep = c11_string__sv(pk_tostr(&argv[1]));
if(sep.size == 0) return ValueError("empty separator");
res = c11_sv__split2(self, sep);
}
py_newlist(py_retval());
for(int i = 0; i < res.length; i++) {
c11_sv part = c11__getitem(c11_sv, &res, i);
if(discard_empty && part.size == 0) continue;
py_newstrv(py_list_emplace(py_retval()), part);
}
c11_vector__dtor(&res);
return true;
}
static bool str_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = pk_tostr(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* sub = pk_tostr(&argv[1]);
int res = c11_sv__count(c11_string__sv(self), c11_string__sv(sub));
py_newint(py_retval(), res);
return true;
}
static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
c11_sv self = c11_string__sv(pk_tostr(&argv[0]));
c11_sv chars;
if(argc == 1) {
chars = (c11_sv){" \t\n\r", 4};
} else if(argc == 2) {
if(!py_checkstr(&argv[1])) return false;
chars = c11_string__sv(pk_tostr(&argv[1]));
} else {
return TypeError("strip() takes at most 2 arguments");
}
c11_sv res = c11_sv__strip(self, chars, left, right);
py_newstrv(py_retval(), res);
return true;
}
static bool str_strip(int argc, py_Ref argv) { return str__strip_impl(true, true, argc, argv); }
static bool str_lstrip(int argc, py_Ref argv) { return str__strip_impl(true, false, argc, argv); }
static bool str_rstrip(int argc, py_Ref argv) { return str__strip_impl(false, true, argc, argv); }
static bool str_zfill(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(pk_tostr(&argv[0]));
PY_CHECK_ARG_TYPE(1, tp_int);
int width = py_toint(py_arg(1));
int delta = width - c11_sv__u8_length(self);
if(delta <= 0) {
*py_retval() = argv[0];
return true;
}
c11_sbuf buf;
c11_sbuf__ctor(&buf);
for(int i = 0; i < delta; i++) {
c11_sbuf__write_char(&buf, '0');
}
c11_sbuf__write_sv(&buf, self);
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool str__widthjust_impl(bool left, int argc, py_Ref argv) {
if(argc > 1 + 2) return TypeError("expected at most 2 arguments");
char pad;
if(argc == 1 + 1) {
pad = ' ';
} else {
if(!py_checkstr(&argv[2])) return false;
c11_string* padstr = pk_tostr(&argv[2]);
if(padstr->size != 1)
return TypeError("The fill character must be exactly one character long");
pad = padstr->data[0];
}
c11_sv self = c11_string__sv(pk_tostr(&argv[0]));
PY_CHECK_ARG_TYPE(1, tp_int);
int width = py_toint(py_arg(1));
if(width <= self.size) {
*py_retval() = argv[0];
return true;
}
c11_sbuf buf;
c11_sbuf__ctor(&buf);
if(left) {
c11_sbuf__write_sv(&buf, self);
for(int i = 0; i < width - self.size; i++) {
c11_sbuf__write_char(&buf, pad);
}
} else {
for(int i = 0; i < width - self.size; i++) {
c11_sbuf__write_char(&buf, pad);
}
c11_sbuf__write_sv(&buf, self);
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool str_ljust(int argc, py_Ref argv) { return str__widthjust_impl(true, argc, argv); }
static bool str_rjust(int argc, py_Ref argv) { return str__widthjust_impl(false, argc, argv); }
static bool str_find(int argc, py_Ref argv) {
if(argc > 3) return TypeError("find() takes at most 3 arguments");
c11_string* self = pk_tostr(&argv[0]);
int start = 0;
if(argc == 3) {
PY_CHECK_ARG_TYPE(2, tp_int);
start = py_toint(py_arg(2));
if(start < 0) start += c11_sv__u8_length(c11_string__sv(self));
if(start < 0) start = 0;
}
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* sub = pk_tostr(&argv[1]);
int res = c11_sv__index2(c11_string__sv(self), c11_string__sv(sub), start);
py_newint(py_retval(), res);
return true;
}
static bool str_index(int argc, py_Ref argv) {
bool ok = str_find(argc, argv);
if(!ok) return false;
if(py_toint(py_retval()) == -1) return ValueError("substring not found");
return true;
}
static bool str_encode(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int size;
const char* data = py_tostrn(argv, &size);
unsigned char* p = py_newbytes(py_retval(), size);
memcpy(p, data, size);
return true;
}
static bool str_format(int argc, py_Ref argv) {
c11_sv self = py_tosv(argv);
py_Ref args = argv + 1;
int64_t auto_field_index = -1;
bool manual_field_used = false;
const char* p_begin = self.data;
const char* p_end = self.data + self.size;
const char* p = p_begin;
c11_sbuf buf;
c11_sbuf__ctor(&buf);
while(p < p_end) {
if(*p == '{') {
if((p + 1) < p_end && p[1] == '{') {
// '{{' -> '{'
c11_sbuf__write_char(&buf, '{');
p += 2;
} else {
if((p + 1) >= p_end) {
c11_sbuf__dtor(&buf);
return ValueError("single '{' encountered in format string");
}
p++;
// parse field
c11_sv field = {p, 0};
while(p < p_end && *p != '}' && *p != ':') {
p++;
}
if(p < p_end) field.size = p - field.data;
// parse spec
c11_sv spec = {p, 0};
if(*p == ':') {
while(p < p_end && *p != '}') {
p++;
}
if(p < p_end) spec.size = p - spec.data;
}
if(p < p_end) {
c11__rtassert(*p == '}');
} else {
c11_sbuf__dtor(&buf);
return ValueError("expected '}' before end of string");
}
// parse auto field
int64_t arg_index;
if(field.size > 0) { // {0}
if(auto_field_index >= 0) {
c11_sbuf__dtor(&buf);
return ValueError(
"cannot switch from automatic field numbering to manual field specification");
}
IntParsingResult res = c11__parse_uint(field, &arg_index, 10);
if(res != IntParsing_SUCCESS) {
c11_sbuf__dtor(&buf);
return ValueError("only integer field name is supported");
}
manual_field_used = true;
} else { // {}
if(manual_field_used) {
c11_sbuf__dtor(&buf);
return ValueError(
"cannot switch from manual field specification to automatic field numbering");
}
auto_field_index++;
arg_index = auto_field_index;
}
// do format
if(arg_index < 0 || arg_index >= (argc - 1)) {
c11_sbuf__dtor(&buf);
return IndexError("replacement index %i out of range for positional args tuple",
arg_index);
}
bool ok = pk_format_object(pk_current_vm, &args[arg_index], spec);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
// append to buf
c11__rtassert(py_isstr(py_retval()));
c11_sv formatted = py_tosv(py_retval());
c11_sbuf__write_sv(&buf, formatted);
p++; // skip '}'
}
} else if(*p == '}') {
if((p + 1) < p_end && p[1] == '}') {
// '}}' -> '}'
c11_sbuf__write_char(&buf, '}');
p += 2;
} else {
c11_sbuf__dtor(&buf);
return ValueError("single '}' encountered in format string");
}
} else {
c11_sbuf__write_char(&buf, *p);
p++;
}
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
py_Type pk_str__register() {
py_Type type = pk_newtype("str", tp_object, NULL, NULL, false, true);
// no need to dtor because the memory is controlled by the object
py_bindmagic(tp_str, __new__, str__new__);
py_bindmagic(tp_str, __hash__, str__hash__);
py_bindmagic(tp_str, __len__, str__len__);
py_bindmagic(tp_str, __mod__, str__mod__);
py_bindmagic(tp_str, __add__, str__add__);
py_bindmagic(tp_str, __mul__, str__mul__);
py_bindmagic(tp_str, __rmul__, str__rmul__);
py_bindmagic(tp_str, __contains__, str__contains__);
py_bindmagic(tp_str, __str__, str__str__);
py_bindmagic(tp_str, __repr__, str__repr__);
py_bindmagic(tp_str, __iter__, str__iter__);
py_bindmagic(tp_str, __getitem__, str__getitem__);
py_bindmagic(tp_str, __eq__, str__eq__);
py_bindmagic(tp_str, __ne__, str__ne__);
py_bindmagic(tp_str, __lt__, str__lt__);
py_bindmagic(tp_str, __le__, str__le__);
py_bindmagic(tp_str, __gt__, str__gt__);
py_bindmagic(tp_str, __ge__, str__ge__);
py_bindmethod(tp_str, "lower", str_lower);
py_bindmethod(tp_str, "upper", str_upper);
py_bindmethod(tp_str, "startswith", str_startswith);
py_bindmethod(tp_str, "endswith", str_endswith);
py_bindmethod(tp_str, "join", str_join);
py_bindmethod(tp_str, "replace", str_replace);
py_bindmethod(tp_str, "split", str_split);
py_bindmethod(tp_str, "count", str_count);
py_bindmethod(tp_str, "strip", str_strip);
py_bindmethod(tp_str, "lstrip", str_lstrip);
py_bindmethod(tp_str, "rstrip", str_rstrip);
py_bindmethod(tp_str, "zfill", str_zfill);
py_bindmethod(tp_str, "ljust", str_ljust);
py_bindmethod(tp_str, "rjust", str_rjust);
py_bindmethod(tp_str, "find", str_find);
py_bindmethod(tp_str, "index", str_index);
py_bindmethod(tp_str, "encode", str_encode);
py_bindmethod(tp_str, "format", str_format);
return type;
}
bool str_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int* ud = py_touserdata(&argv[0]);
int size;
const char* data = py_tostrn(py_getslot(argv, 0), &size);
if(*ud == size) return StopIteration();
int start = *ud;
int len = c11__u8_header(data[*ud], false);
*ud += len;
py_newstrv(py_retval(), (c11_sv){data + start, len});
return true;
}
py_Type pk_str_iterator__register() {
py_Type type = pk_newtype("str_iterator", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, str_iterator__next__);
return type;
}
static bool bytes__new__(int argc, py_Ref argv) {
if(argc == 1) {
py_newbytes(py_retval(), 0);
return true;
}
if(argc > 2) return TypeError("bytes() takes at most 1 argument");
py_TValue* p;
int length = pk_arrayview(&argv[1], &p);
if(length == -1) return TypeError("bytes() argument must be a list or tuple");
unsigned char* data = py_newbytes(py_retval(), length);
for(int i = 0; i < length; i++) {
if(!py_checktype(&p[i], tp_int)) return false;
py_i64 v = py_toint(&p[i]);
if(v < 0 || v > 255) return ValueError("bytes must be in range(0, 256)");
data[i] = v;
}
return true;
}
static bool bytes__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_bytes* self = py_touserdata(&argv[0]);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, 'b');
c11_sbuf__write_quoted(&buf, (c11_sv){(const char*)self->data, self->size}, '\'');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool bytes__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
int size;
unsigned char* data = py_tobytes(&argv[0], &size);
py_Ref _1 = py_arg(1);
if(_1->type == tp_int) {
int index = py_toint(_1);
if(!pk__normalize_index(&index, size)) return false;
py_newint(py_retval(), data[index]);
return true;
} else if(_1->type == tp_slice) {
int start, stop, step;
bool ok = pk__parse_int_slice(_1, size, &start, &stop, &step);
if(!ok) return false;
c11_vector res;
c11_vector__ctor(&res, sizeof(unsigned char));
for(int i = start; step > 0 ? i < stop : i > stop; i += step) {
c11_vector__push(unsigned char, &res, data[i]);
}
unsigned char* p = py_newbytes(py_retval(), res.length);
memcpy(p, res.data, res.length);
c11_vector__dtor(&res);
return true;
} else {
return TypeError("bytes indices must be integers");
}
}
static bool bytes__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_bytes* self = py_touserdata(&argv[0]);
if(!py_istype(&argv[1], tp_bytes)) {
py_newnotimplemented(py_retval());
} else {
c11_bytes* other = py_touserdata(&argv[1]);
py_newbool(py_retval(), c11_bytes__eq(self, other));
}
return true;
}
static bool bytes__ne__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_bytes* self = py_touserdata(&argv[0]);
if(!py_istype(&argv[1], tp_bytes)) {
py_newnotimplemented(py_retval());
} else {
c11_bytes* other = py_touserdata(&argv[1]);
py_newbool(py_retval(), !c11_bytes__eq(self, other));
}
return true;
}
static bool bytes__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_bytes* self = py_touserdata(&argv[0]);
uint64_t res = 0;
for(int i = 0; i < self->size; i++) {
res = res * 31 + self->data[i];
}
py_newint(py_retval(), res);
return true;
}
static bool bytes__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_bytes* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_bytes) {
py_newnotimplemented(py_retval());
} else {
c11_bytes* other = py_touserdata(&argv[1]);
unsigned char* p = py_newbytes(py_retval(), self->size + other->size);
memcpy(p, self->data, self->size);
memcpy(p + self->size, other->data, other->size);
}
return true;
}
static bool bytes_decode(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int size;
unsigned char* data = py_tobytes(&argv[0], &size);
py_newstrv(py_retval(), (c11_sv){(const char*)data, size});
return true;
}
static bool bytes__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_bytes* self = py_touserdata(&argv[0]);
py_newint(py_retval(), self->size);
return true;
}
py_Type pk_bytes__register() {
py_Type type = pk_newtype("bytes", tp_object, NULL, NULL, false, true);
// no need to dtor because the memory is controlled by the object
py_bindmagic(tp_bytes, __new__, bytes__new__);
py_bindmagic(tp_bytes, __repr__, bytes__repr__);
py_bindmagic(tp_bytes, __getitem__, bytes__getitem__);
py_bindmagic(tp_bytes, __eq__, bytes__eq__);
py_bindmagic(tp_bytes, __ne__, bytes__ne__);
py_bindmagic(tp_bytes, __add__, bytes__add__);
py_bindmagic(tp_bytes, __hash__, bytes__hash__);
py_bindmagic(tp_bytes, __len__, bytes__len__);
py_bindmethod(tp_bytes, "decode", bytes_decode);
return type;
}
#undef DEF_STR_CMP_OP
// src/common\algorithm.c
#include <string.h>
static bool _stable_sort_merge(char* a,
char* a_end,
char* b,
char* b_end,
char* r,
int elem_size,
int (*f_lt)(const void* a, const void* b, void* extra),
void* extra) {
while(a < a_end && b < b_end) {
int res = f_lt(b, a, extra);
// check error
if(res == -1) return false;
if(res == 0) { // !(b<a) -> (b>=a) -> (a<=b)
memcpy(r, a, elem_size);
a += elem_size;
} else {
memcpy(r, b, elem_size);
b += elem_size;
}
r += elem_size;
}
// one of the arrays is empty
for(; a < a_end; a += elem_size, r += elem_size)
memcpy(r, a, elem_size);
for(; b < b_end; b += elem_size, r += elem_size)
memcpy(r, b, elem_size);
return true;
}
bool c11__stable_sort(void* ptr_,
int length,
int elem_size,
int (*f_lt)(const void* a, const void* b, void* extra),
void* extra) {
// merge sort
char *ptr = ptr_, *tmp = PK_MALLOC(length * elem_size);
for(int seg = 1; seg < length; seg *= 2) {
for(char* a = ptr; a < ptr + (length - seg) * elem_size; a += 2 * seg * elem_size) {
char *b = a + seg * elem_size, *a_end = b, *b_end = b + seg * elem_size;
if(b_end > ptr + length * elem_size) b_end = ptr + length * elem_size;
bool ok = _stable_sort_merge(a, a_end, b, b_end, tmp, elem_size, f_lt, extra);
if(!ok) {
PK_FREE(tmp);
return false;
}
memcpy(a, tmp, b_end - a);
}
}
PK_FREE(tmp);
return true;
}
// src/common\chunkedvector.c
#include <assert.h>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
PK_INLINE int c11__bit_length(unsigned long x) {
#if(defined(__clang__) || defined(__GNUC__))
return x == 0 ? 0 : (int)sizeof(unsigned long) * 8 - __builtin_clzl(x);
#elif defined(_MSC_VER)
_Static_assert(sizeof(unsigned long) <= 4, "unsigned long is greater than 4 bytes");
unsigned long msb;
if(_BitScanReverse(&msb, x)) { return (int)msb + 1; }
return 0;
#else
const int BIT_LENGTH_TABLE[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
int msb = 0;
while(x >= 32) {
msb += 6;
x >>= 6;
}
msb += BIT_LENGTH_TABLE[x];
return msb;
#endif
}
void c11_chunkedvector__ctor(c11_chunkedvector* self, int elem_size, int initial_chunks) {
if(initial_chunks < 5) initial_chunks = 5;
c11_vector__ctor(&self->chunks, sizeof(c11_chunkedvector_chunk));
self->length = 0;
self->capacity = (1U << (unsigned int)initial_chunks) - 1U;
self->elem_size = elem_size;
self->initial_chunks = initial_chunks;
void* chunks_data = PK_MALLOC(elem_size * ((1U << (unsigned int)initial_chunks) - 1));
for(int i = 0; i < initial_chunks; i++) {
c11_chunkedvector_chunk chunk = {.length = 0,
.capacity = 1U << i,
.data = (char*)chunks_data + elem_size * ((1U << i) - 1U)};
c11_vector__push(c11_chunkedvector_chunk, &self->chunks, chunk);
}
}
void c11_chunkedvector__dtor(c11_chunkedvector* self) {
for(int index = self->initial_chunks; index < self->chunks.length; index++) {
c11_chunkedvector_chunk* chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, index);
PK_FREE(chunk->data);
}
c11_chunkedvector_chunk* initial_chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, 0);
PK_FREE(initial_chunk->data);
c11_vector__dtor(&self->chunks);
}
void* c11_chunkedvector__emplace(c11_chunkedvector* self) {
if(self->length == self->capacity) {
#ifndef NDEBUG
c11_chunkedvector_chunk last_chunk =
c11_vector__back(c11_chunkedvector_chunk, &self->chunks);
assert(last_chunk.capacity == last_chunk.length);
#endif
c11_chunkedvector_chunk chunk = {
.length = 0,
.capacity = 1U << (unsigned int)self->chunks.length,
.data = PK_MALLOC(self->elem_size * ((1U << (unsigned int)self->chunks.length)))};
self->capacity += chunk.capacity;
c11_vector__push(c11_chunkedvector_chunk, &self->chunks, chunk);
}
#if 1
int last_chunk_index = c11__bit_length(self->length + 1) - 1;
c11_chunkedvector_chunk* last_chunk =
c11__at(c11_chunkedvector_chunk, &self->chunks, last_chunk_index);
#else
// This is not correct, because there is some pre-allocated chunks
c11_chunkedvector_chunk* last_chunk = &c11_vector__back(c11_chunkedvector_chunk, &self->chunks);
#endif
void* p = (char*)last_chunk->data + self->elem_size * last_chunk->length;
last_chunk->length++;
self->length++;
return p;
}
void* c11_chunkedvector__at(c11_chunkedvector* self, int index) {
int chunk_index = c11__bit_length(index + 1) - 1;
c11_chunkedvector_chunk* chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, chunk_index);
return (char*)chunk->data + (index + 1 - (1U << (unsigned int)chunk_index)) * self->elem_size;
}
// src/common\dmath.c
#include <stdint.h>
union Float64Bits {
double f;
uint64_t i;
};
/* IEEE 754 double precision floating point data manipulation */
typedef union
{
double f;
uint64_t u;
struct {int32_t i0,i1;} s;
} udi_t;
// https://github.com/akohlmey/fastermath/blob/master/src/exp.c#L63
double dmath_exp2(double x) {
if (x > 1000) return DMATH_INFINITY;
if (x < -1000) return 0;
if (dmath_isnan(x)) return DMATH_NAN;
const int FM_DOUBLE_BIAS = 1023;
static const double fm_exp2_q[] = {
/* 1.00000000000000000000e0, */
2.33184211722314911771e2,
4.36821166879210612817e3
};
static const double fm_exp2_p[] = {
2.30933477057345225087e-2,
2.02020656693165307700e1,
1.51390680115615096133e3
};
double ipart, fpart, px, qx;
udi_t epart;
ipart = dmath_floor(x+0.5);
fpart = x - ipart;
// FM_DOUBLE_INIT_EXP(epart,ipart);
epart.s.i0 = 0;
epart.s.i1 = (((int) ipart) + FM_DOUBLE_BIAS) << 20;
x = fpart*fpart;
px = fm_exp2_p[0];
px = px*x + fm_exp2_p[1];
qx = x + fm_exp2_q[0];
px = px*x + fm_exp2_p[2];
qx = qx*x + fm_exp2_q[1];
px = px * fpart;
x = 1.0 + 2.0*(px/(qx-px));
return epart.f*x;
}
double dmath_log2(double x) {
if(x < 0) return DMATH_NAN;
if(x == 0) return -DMATH_INFINITY;
if(x == DMATH_INFINITY) return DMATH_INFINITY;
if(dmath_isnan(x)) return DMATH_NAN;
const double fm_log_dinv = 4.09600000000000000000e+03;
const double fm_log_dsq6 = 9.93410746256510361521e-09;
const int FM_DOUBLE_BIAS = 1023;
const int FM_DOUBLE_EMASK = 2146435072;
const int FM_DOUBLE_MBITS = 20;
const int FM_DOUBLE_MMASK = 1048575;
const int FM_DOUBLE_EZERO = 1072693248;
const int FM_SPLINE_SHIFT = 8;
udi_t val;
double a,b,y;
int32_t hx, ipart;
val.f = x;
hx = val.s.i1;
/* extract exponent and subtract bias */
ipart = (((hx & FM_DOUBLE_EMASK) >> FM_DOUBLE_MBITS) - FM_DOUBLE_BIAS);
/* mask out exponent to get the prefactor to 2**ipart */
hx &= FM_DOUBLE_MMASK;
val.s.i1 = hx | FM_DOUBLE_EZERO;
x = val.f;
/* table index */
hx >>= FM_SPLINE_SHIFT;
/* compute x value matching table index */
val.s.i0 = 0;
val.s.i1 = FM_DOUBLE_EZERO | (hx << FM_SPLINE_SHIFT);
b = (x - val.f) * fm_log_dinv;
a = 1.0 - b;
/* evaluate spline */
y = a * fm_log_q1[hx] + b * fm_log_q1[hx+1];
a = (a*a*a-a) * fm_log_q2[hx];
b = (b*b*b-b) * fm_log_q2[hx+1];
y += (a + b) * fm_log_dsq6;
return ((double) ipart) + (y * DMATH_LOG2_E);
}
double dmath_exp(double x) {
return dmath_exp2(x * DMATH_LOG2_E); // log2(e)
}
double dmath_exp10(double x) {
return dmath_exp2(x * 3.321928094887362); // log2(10)
}
double dmath_log(double x) {
return dmath_log2(x) / DMATH_LOG2_E; // log2(e)
}
double dmath_log10(double x) {
return dmath_log2(x) / 3.321928094887362; // log2(10)
}
double dmath_pow(double base, double exp) {
int exp_int = (int)exp;
if(exp_int == exp) {
if(exp_int == 0) return 1;
if(exp_int < 0) {
base = 1 / base;
exp_int = -exp_int;
}
double res = 1;
while(exp_int > 0) {
if(exp_int & 1) res *= base;
base *= base;
exp_int >>= 1;
}
return res;
}
if (base > 0) {
return dmath_exp(exp * dmath_log(base));
}
if (base == 0) {
if (exp > 0) return 0;
if (exp == 0) return 1;
}
return DMATH_NAN;
}
double dmath_sqrt(double x) {
return dmath_pow(x, 0.5);
}
double dmath_cbrt(double x) {
return dmath_pow(x, 1.0 / 3.0);
}
// https://github.com/kraj/musl/blob/kraj/master/src/math/sincos.c
static double __sin(double x, double y, int iy)
{
static const double
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
double z,r,v,w;
z = x*x;
w = z*z;
r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6);
v = z*x;
if (iy == 0)
return x + v*(S1 + z*r);
else
return x - ((z*(0.5*y - v*r) - y) - v*S1);
}
static double __cos(double x, double y)
{
static const double
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
double hz,z,r,w;
z = x*x;
w = z*z;
r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6));
hz = 0.5*z;
w = 1.0-hz;
return w + (((1.0-w)-hz) + (z*r-x*y));
}
int __rem_pio2(double x, double *y)
{
static const double
toint = 1.5/2.22044604925031308085e-16,
pio4 = 0x1.921fb54442d18p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
union Float64Bits u = { .f = x };
double z,w,t,r,fn;
double tx[3],ty[2];
uint32_t ix;
int sign, n, ex, ey, i;
sign = u.i>>63;
ix = u.i>>32 & 0x7fffffff;
if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
goto medium; /* cancellation -- use medium case */
if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */
if (!sign) {
z = x - pio2_1; /* one round good to 85 bits */
y[0] = z - pio2_1t;
y[1] = (z-y[0]) - pio2_1t;
return 1;
} else {
z = x + pio2_1;
y[0] = z + pio2_1t;
y[1] = (z-y[0]) + pio2_1t;
return -1;
}
} else {
if (!sign) {
z = x - 2*pio2_1;
y[0] = z - 2*pio2_1t;
y[1] = (z-y[0]) - 2*pio2_1t;
return 2;
} else {
z = x + 2*pio2_1;
y[0] = z + 2*pio2_1t;
y[1] = (z-y[0]) + 2*pio2_1t;
return -2;
}
}
}
if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */
if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */
goto medium;
if (!sign) {
z = x - 3*pio2_1;
y[0] = z - 3*pio2_1t;
y[1] = (z-y[0]) - 3*pio2_1t;
return 3;
} else {
z = x + 3*pio2_1;
y[0] = z + 3*pio2_1t;
y[1] = (z-y[0]) + 3*pio2_1t;
return -3;
}
} else {
if (ix == 0x401921fb) /* |x| ~= 4pi/2 */
goto medium;
if (!sign) {
z = x - 4*pio2_1;
y[0] = z - 4*pio2_1t;
y[1] = (z-y[0]) - 4*pio2_1t;
return 4;
} else {
z = x + 4*pio2_1;
y[0] = z + 4*pio2_1t;
y[1] = (z-y[0]) + 4*pio2_1t;
return -4;
}
}
}
if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
medium:
/* rint(x/(pi/2)) */
fn = (double)x*invpio2 + toint - toint;
n = (int32_t)fn;
r = x - fn*pio2_1;
w = fn*pio2_1t; /* 1st round, good to 85 bits */
/* Matters with directed rounding. */
if ((r - w < -pio4)) {
n--;
fn--;
r = x - fn*pio2_1;
w = fn*pio2_1t;
} else if ((r - w > pio4)) {
n++;
fn++;
r = x - fn*pio2_1;
w = fn*pio2_1t;
}
y[0] = r - w;
u.f = y[0];
ey = u.i>>52 & 0x7ff;
ex = ix>>20;
if (ex - ey > 16) { /* 2nd round, good to 118 bits */
t = r;
w = fn*pio2_2;
r = t - w;
w = fn*pio2_2t - ((t-r)-w);
y[0] = r - w;
u.f = y[0];
ey = u.i>>52 & 0x7ff;
if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */
t = r;
w = fn*pio2_3;
r = t - w;
w = fn*pio2_3t - ((t-r)-w);
y[0] = r - w;
}
}
y[1] = (r - y[0]) - w;
return n;
}
(void)tx;
(void)ty;
(void)i;
return 0;
#if 0
/*
* all other (large) arguments
*/
if (ix >= 0x7ff00000) { /* x is inf or NaN */
y[0] = y[1] = x - x;
return 0;
}
/* set z = scalbn(|x|,-ilogb(x)+23) */
u.f = x;
u.i &= (uint64_t)-1>>12;
u.i |= (uint64_t)(0x3ff + 23)<<52;
z = u.f;
for (i=0; i < 2; i++) {
tx[i] = (double)(int32_t)z;
z = (z-tx[i])*0x1p24;
}
tx[i] = z;
/* skip zero terms, first term is non-zero */
while (tx[i] == 0.0)
i--;
n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1);
if (sign) {
y[0] = -ty[0];
y[1] = -ty[1];
return -n;
}
y[0] = ty[0];
y[1] = ty[1];
return n;
#endif
}
void dmath_sincos(double x, double *sin, double *cos) {
double y[2], s, c;
uint32_t ix;
unsigned n;
//GET_HIGH_WORD(ix, x);
union Float64Bits u = { .f = x };
ix = (uint32_t)(u.i >> 32);
ix &= 0x7fffffff;
/* |x| ~< pi/4 */
if (ix <= 0x3fe921fb) {
/* if |x| < 2**-27 * sqrt(2) */
if (ix < 0x3e46a09e) {
/* raise inexact if x!=0 and underflow if subnormal */
// FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
volatile double y_force_eval;
y_force_eval = ix < 0x00100000 ? x/0x1p120f : x+0x1p120f;
(void)y_force_eval;
*sin = x;
*cos = 1.0;
return;
}
*sin = __sin(x, 0.0, 0);
*cos = __cos(x, 0.0);
return;
}
/* sincos(Inf or NaN) is NaN */
if (ix >= 0x7ff00000) {
*sin = *cos = x - x;
return;
}
/* argument reduction needed */
n = __rem_pio2(x, y);
s = __sin(y[0], y[1], 1);
c = __cos(y[0], y[1]);
switch (n&3) {
case 0:
*sin = s;
*cos = c;
break;
case 1:
*sin = c;
*cos = -s;
break;
case 2:
*sin = -s;
*cos = -c;
break;
case 3:
default:
*sin = -c;
*cos = s;
break;
}
}
double dmath_sin(double x) {
double s, c;
dmath_sincos(x, &s, &c);
return s;
}
double dmath_cos(double x) {
double s, c;
dmath_sincos(x, &s, &c);
return c;
}
double dmath_tan(double x) {
double s, c;
dmath_sincos(x, &s, &c);
return s / c;
}
static double zig_r64(double z) {
const double pS0 = 1.66666666666666657415e-01;
const double pS1 = -3.25565818622400915405e-01;
const double pS2 = 2.01212532134862925881e-01;
const double pS3 = -4.00555345006794114027e-02;
const double pS4 = 7.91534994289814532176e-04;
const double pS5 = 3.47933107596021167570e-05;
const double qS1 = -2.40339491173441421878e+00;
const double qS2 = 2.02094576023350569471e+00;
const double qS3 = -6.88283971605453293030e-01;
const double qS4 = 7.70381505559019352791e-02;
double p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
double q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
return p / q;
}
// https://github.com/ziglang/zig/blob/master/lib/std/math/asin.zig
double dmath_asin(double x) {
const double pio2_hi = 1.57079632679489655800e+00;
const double pio2_lo = 6.12323399573676603587e-17;
union Float64Bits ux_union;
ux_union.f = x;
uint64_t ux = ux_union.i;
uint32_t hx = (uint32_t)(ux >> 32);
uint32_t ix = hx & 0x7FFFFFFF;
/* |x| >= 1 or nan */
if (ix >= 0x3FF00000) {
uint32_t lx = (uint32_t)(ux & 0xFFFFFFFF);
/* asin(1) = +-pi/2 with inexact */
if (((ix - 0x3FF00000) | lx) == 0) {
return x * pio2_hi + 0x1.0p-120;
} else {
return DMATH_NAN;
}
}
/* |x| < 0.5 */
if (ix < 0x3FE00000) {
/* if 0x1p-1022 <= |x| < 0x1p-26 avoid raising overflow */
if (ix < 0x3E500000 && ix >= 0x00100000) {
return x;
} else {
return x + x * zig_r64(x * x);
}
}
/* 1 > |x| >= 0.5 */
double z = (1 - dmath_fabs(x)) * 0.5;
double s = dmath_sqrt(z);
double r = zig_r64(z);
double fx;
/* |x| > 0.975 */
if (ix >= 0x3FEF3333) {
fx = pio2_hi - 2 * (s + s * r);
} else {
union Float64Bits jx_union = { .f = s };
uint64_t jx = jx_union.i;
union Float64Bits df_union = { .i = jx & 0xFFFFFFFF00000000ULL };
double df = df_union.f;
double c = (z - df * df) / (s + df);
fx = 0.5 * pio2_hi - (2 * s * r - (pio2_lo - 2 * c) - (0.5 * pio2_hi - 2 * df));
}
if (hx >> 31 != 0) {
return -fx;
} else {
return fx;
}
}
double dmath_acos(double x) {
return DMATH_PI / 2 - dmath_asin(x);
}
double dmath_atan(double x) {
return dmath_asin(x / dmath_sqrt(1 + x * x));
}
double dmath_atan2(double y, double x) {
if (x > 0) {
return dmath_atan(y / x);
} else if (x < 0 && y >= 0) {
return dmath_atan(y / x) + DMATH_PI;
} else if (x < 0 && y < 0) {
return dmath_atan(y / x) - DMATH_PI;
} else if (x == 0 && y > 0) {
return DMATH_PI / 2;
} else if (x == 0 && y < 0) {
return -DMATH_PI / 2;
} else {
return DMATH_NAN;
}
}
////////////////////////////////////////////////////////////////////
int dmath_isinf(double x) {
union Float64Bits u = { .f = x };
return (u.i & -1ULL>>1) == 0x7ffULL<<52;
}
int dmath_isnan(double x) {
union Float64Bits u = { .f = x };
return (u.i & -1ULL>>1) > 0x7ffULL<<52;
}
int dmath_isnormal(double x) {
union Float64Bits u = { .f = x };
return ((u.i+(1ULL<<52)) & -1ULL>>1) >= 1ULL<<53;
}
int dmath_isfinite(double x) {
union Float64Bits u = { .f = x };
return (u.i & -1ULL>>1) < 0x7ffULL<<52;
}
// https://github.com/kraj/musl/blob/kraj/master/src/math/fmod.c
double dmath_fmod(double x, double y) {
union Float64Bits ux = { .f = x }, uy = { .f = y };
int ex = ux.i>>52 & 0x7ff;
int ey = uy.i>>52 & 0x7ff;
int sx = ux.i>>63;
uint64_t i;
/* in the followings uxi should be ux.i, but then gcc wrongly adds */
/* float load/store to inner loops ruining performance and code size */
uint64_t uxi = ux.i;
if (uy.i<<1 == 0 || dmath_isnan(y) || ex == 0x7ff)
return (x*y)/(x*y);
if (uxi<<1 <= uy.i<<1) {
if (uxi<<1 == uy.i<<1)
return 0*x;
return x;
}
/* normalize x and y */
if (!ex) {
for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1);
uxi <<= -ex + 1;
} else {
uxi &= -1ULL >> 12;
uxi |= 1ULL << 52;
}
if (!ey) {
for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1);
uy.i <<= -ey + 1;
} else {
uy.i &= -1ULL >> 12;
uy.i |= 1ULL << 52;
}
/* x mod y */
for (; ex > ey; ex--) {
i = uxi - uy.i;
if (i >> 63 == 0) {
if (i == 0)
return 0*x;
uxi = i;
}
uxi <<= 1;
}
i = uxi - uy.i;
if (i >> 63 == 0) {
if (i == 0)
return 0*x;
uxi = i;
}
for (; uxi>>52 == 0; uxi <<= 1, ex--);
/* scale result */
if (ex > 0) {
uxi -= 1ULL << 52;
uxi |= (uint64_t)ex << 52;
} else {
uxi >>= -ex + 1;
}
uxi |= (uint64_t)sx << 63;
ux.i = uxi;
return ux.f;
}
// https://github.com/kraj/musl/blob/kraj/master/src/math/copysign.c
double dmath_copysign(double x, double y) {
union Float64Bits ux = { .f = x }, uy = { .f = y };
ux.i &= -1ULL/2;
ux.i |= uy.i & 1ULL<<63;
return ux.f;
}
double dmath_fabs(double x) {
return (x < 0) ? -x : x;
}
double dmath_ceil(double x) {
if(!dmath_isfinite(x)) return x;
int int_part = (int)x;
if (x > 0 && x != (double)int_part) {
return (double)(int_part + 1);
}
return (double)int_part;
}
double dmath_floor(double x) {
if(!dmath_isfinite(x)) return x;
int int_part = (int)x;
if (x < 0 && x != (double)int_part) {
return (double)(int_part - 1);
}
return (double)int_part;
}
double dmath_trunc(double x) {
return (double)((int)x);
}
// https://github.com/kraj/musl/blob/kraj/master/src/math/modf.c
double dmath_modf(double x, double* iptr) {
union Float64Bits u = { .f = x };
uint64_t mask;
int e = (int)(u.i>>52 & 0x7ff) - 0x3ff;
/* no fractional part */
if (e >= 52) {
*iptr = x;
if (e == 0x400 && u.i<<12 != 0) /* nan */
return x;
u.i &= 1ULL<<63;
return u.f;
}
/* no integral part*/
if (e < 0) {
u.i &= 1ULL<<63;
*iptr = u.f;
return x;
}
mask = -1ULL>>12>>e;
if ((u.i & mask) == 0) {
*iptr = x;
u.i &= 1ULL<<63;
return u.f;
}
u.i &= ~mask;
*iptr = u.f;
return x - u.f;
}
double dmath_fmin(double x, double y) {
return (x < y) ? x : y;
}
double dmath_fmax(double x, double y) {
return (x > y) ? x : y;
}
// src/common\memorypool.c
#include <stdbool.h>
void FixedMemoryPool__ctor(FixedMemoryPool* self, int BlockSize, int BlockCount) {
self->BlockSize = BlockSize;
self->BlockCount = BlockCount;
self->exceeded_bytes = 0;
self->data = PK_MALLOC(BlockSize * BlockCount);
self->data_end = self->data + BlockSize * BlockCount;
self->_free_list = PK_MALLOC(sizeof(void*) * BlockCount);
self->_free_list_length = BlockCount;
for(int i = 0; i < BlockCount; i++) {
self->_free_list[i] = self->data + i * BlockSize;
}
}
void FixedMemoryPool__dtor(FixedMemoryPool* self) {
PK_FREE(self->_free_list);
PK_FREE(self->data);
}
void* FixedMemoryPool__alloc(FixedMemoryPool* self) {
if(self->_free_list_length > 0) {
self->_free_list_length--;
return self->_free_list[self->_free_list_length];
} else {
self->exceeded_bytes += self->BlockSize;
return PK_MALLOC(self->BlockSize);
}
}
void FixedMemoryPool__dealloc(FixedMemoryPool* self, void* p) {
bool is_valid = (char*)p >= self->data && (char*)p < self->data_end;
if(is_valid) {
self->_free_list[self->_free_list_length] = p;
self->_free_list_length++;
} else {
self->exceeded_bytes -= self->BlockSize;
PK_FREE(p);
}
}
// static int FixedMemoryPool__used_bytes(FixedMemoryPool* self) {
// return (self->_free_list_end - self->_free_list) * self->BlockSize;
// }
// static int FixedMemoryPool__total_bytes(FixedMemoryPool* self) {
// return self->BlockCount * self->BlockSize;
// }
// src/common\name.c
#if PK_ENABLE_CUSTOM_SNAME == 0
#include <assert.h>
typedef struct NameBucket NameBucket;
typedef struct NameBucket {
NameBucket* next;
uint64_t hash;
int size; // size of the data excluding the null-terminator
char data[]; // null-terminated data
} NameBucket;
static struct {
NameBucket* table[0x10000];
#if PK_ENABLE_THREADS
atomic_flag lock;
#endif
} pk_string_table;
#define MAGIC_METHOD(x) py_Name x;
#ifdef MAGIC_METHOD
// math operators
MAGIC_METHOD(__lt__)
MAGIC_METHOD(__le__)
MAGIC_METHOD(__gt__)
MAGIC_METHOD(__ge__)
/////////////////////////////
MAGIC_METHOD(__neg__)
MAGIC_METHOD(__abs__)
MAGIC_METHOD(__round__)
MAGIC_METHOD(__divmod__)
/////////////////////////////
MAGIC_METHOD(__add__)
MAGIC_METHOD(__radd__)
MAGIC_METHOD(__sub__)
MAGIC_METHOD(__rsub__)
MAGIC_METHOD(__mul__)
MAGIC_METHOD(__rmul__)
MAGIC_METHOD(__truediv__)
MAGIC_METHOD(__rtruediv__)
MAGIC_METHOD(__floordiv__)
MAGIC_METHOD(__rfloordiv__)
MAGIC_METHOD(__mod__)
MAGIC_METHOD(__rmod__)
MAGIC_METHOD(__pow__)
MAGIC_METHOD(__rpow__)
MAGIC_METHOD(__matmul__)
MAGIC_METHOD(__lshift__)
MAGIC_METHOD(__rshift__)
MAGIC_METHOD(__and__)
MAGIC_METHOD(__or__)
MAGIC_METHOD(__xor__)
/////////////////////////////
MAGIC_METHOD(__repr__)
MAGIC_METHOD(__str__)
MAGIC_METHOD(__hash__)
MAGIC_METHOD(__len__)
MAGIC_METHOD(__iter__)
MAGIC_METHOD(__next__)
MAGIC_METHOD(__contains__)
MAGIC_METHOD(__bool__)
MAGIC_METHOD(__invert__)
/////////////////////////////
MAGIC_METHOD(__eq__)
MAGIC_METHOD(__ne__)
// indexer
MAGIC_METHOD(__getitem__)
MAGIC_METHOD(__setitem__)
MAGIC_METHOD(__delitem__)
// specials
MAGIC_METHOD(__new__)
MAGIC_METHOD(__init__)
MAGIC_METHOD(__call__)
MAGIC_METHOD(__enter__)
MAGIC_METHOD(__exit__)
MAGIC_METHOD(__name__)
MAGIC_METHOD(__all__)
MAGIC_METHOD(__package__)
MAGIC_METHOD(__class__)
MAGIC_METHOD(__getattr__)
MAGIC_METHOD(__reduce__)
MAGIC_METHOD(__missing__)
#endif
#undef MAGIC_METHOD
void pk_names_initialize() {
#define MAGIC_METHOD(x) x = py_name(#x);
#ifdef MAGIC_METHOD
// math operators
MAGIC_METHOD(__lt__)
MAGIC_METHOD(__le__)
MAGIC_METHOD(__gt__)
MAGIC_METHOD(__ge__)
/////////////////////////////
MAGIC_METHOD(__neg__)
MAGIC_METHOD(__abs__)
MAGIC_METHOD(__round__)
MAGIC_METHOD(__divmod__)
/////////////////////////////
MAGIC_METHOD(__add__)
MAGIC_METHOD(__radd__)
MAGIC_METHOD(__sub__)
MAGIC_METHOD(__rsub__)
MAGIC_METHOD(__mul__)
MAGIC_METHOD(__rmul__)
MAGIC_METHOD(__truediv__)
MAGIC_METHOD(__rtruediv__)
MAGIC_METHOD(__floordiv__)
MAGIC_METHOD(__rfloordiv__)
MAGIC_METHOD(__mod__)
MAGIC_METHOD(__rmod__)
MAGIC_METHOD(__pow__)
MAGIC_METHOD(__rpow__)
MAGIC_METHOD(__matmul__)
MAGIC_METHOD(__lshift__)
MAGIC_METHOD(__rshift__)
MAGIC_METHOD(__and__)
MAGIC_METHOD(__or__)
MAGIC_METHOD(__xor__)
/////////////////////////////
MAGIC_METHOD(__repr__)
MAGIC_METHOD(__str__)
MAGIC_METHOD(__hash__)
MAGIC_METHOD(__len__)
MAGIC_METHOD(__iter__)
MAGIC_METHOD(__next__)
MAGIC_METHOD(__contains__)
MAGIC_METHOD(__bool__)
MAGIC_METHOD(__invert__)
/////////////////////////////
MAGIC_METHOD(__eq__)
MAGIC_METHOD(__ne__)
// indexer
MAGIC_METHOD(__getitem__)
MAGIC_METHOD(__setitem__)
MAGIC_METHOD(__delitem__)
// specials
MAGIC_METHOD(__new__)
MAGIC_METHOD(__init__)
MAGIC_METHOD(__call__)
MAGIC_METHOD(__enter__)
MAGIC_METHOD(__exit__)
MAGIC_METHOD(__name__)
MAGIC_METHOD(__all__)
MAGIC_METHOD(__package__)
MAGIC_METHOD(__class__)
MAGIC_METHOD(__getattr__)
MAGIC_METHOD(__reduce__)
MAGIC_METHOD(__missing__)
#endif
#undef MAGIC_METHOD
}
void pk_names_finalize() {
for(int i = 0; i < 0x10000; i++) {
NameBucket* p = pk_string_table.table[i];
while(p) {
NameBucket* next = p->next;
PK_FREE(p);
p = next;
}
pk_string_table.table[i] = NULL;
}
}
py_Name py_namev(c11_sv name) {
#if PK_ENABLE_THREADS
while(atomic_flag_test_and_set(&pk_string_table.lock)) {
c11_thrd__yield();
}
#endif
uint64_t hash = c11_sv__hash(name);
int index = hash & 0xFFFF;
NameBucket* p = pk_string_table.table[index];
NameBucket* prev = NULL;
bool found = false;
while(p) {
c11_sv p_sv = {p->data, p->size};
if(p->hash == hash && c11__sveq(p_sv, name)) {
found = true;
break;
}
prev = p;
p = p->next;
}
if(found) {
#if PK_ENABLE_THREADS
atomic_flag_clear(&pk_string_table.lock);
#endif
return (py_Name)p;
}
// generate new index
NameBucket* bucket = PK_MALLOC(sizeof(NameBucket) + name.size + 1);
bucket->next = NULL;
bucket->hash = hash;
bucket->size = name.size;
memcpy(bucket->data, name.data, name.size);
bucket->data[name.size] = '\0';
if(prev == NULL) {
pk_string_table.table[index] = bucket;
} else {
assert(prev->next == NULL);
prev->next = bucket;
}
#if PK_ENABLE_THREADS
atomic_flag_clear(&pk_string_table.lock);
#endif
return (py_Name)bucket;
}
c11_sv py_name2sv(py_Name index) {
NameBucket* p = (NameBucket*)index;
return (c11_sv){p->data, p->size};
}
py_Name py_name(const char* name) {
c11_sv sv;
sv.data = name;
sv.size = strlen(name);
return py_namev(sv);
}
const char* py_name2str(py_Name index) {
NameBucket* p = (NameBucket*)index;
return p->data;
}
#endif
// src/common\serialize.c
// >>> ord('🥕')
// 129365
// >>> ord('🍋')
// 127819
static uint32_t c11__checksum_32bit(const void* data, int size){
const uint8_t* p = (const uint8_t*)data;
uint32_t res = 0;
for(int i = 0; i < size; i++){
res = res * 31 + p[i];
}
return res;
}
void c11_serializer__ctor(c11_serializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver){
c11_vector__ctor(&self->data, 1);
c11_serializer__write_i16(self, magic);
c11_serializer__write_i8(self, major_ver);
c11_serializer__write_i8(self, minor_ver);
}
void c11_serializer__dtor(c11_serializer* self){
c11_vector__dtor(&self->data);
}
void c11_serializer__write_mark(c11_serializer *self, char mark) {
c11_serializer__write_i8(self, (int8_t)mark);
}
void c11_serializer__write_cstr(c11_serializer *self, const char* cstr) {
int len = (int)strlen(cstr);
c11_serializer__write_bytes(self, cstr, len + 1);
}
void c11_serializer__write_bytes(c11_serializer* self, const void* data, int size){
c11_vector__extend(&self->data, data, size);
}
void* c11_serializer__submit(c11_serializer* self, int* size){
uint32_t checksum = c11__checksum_32bit(self->data.data, self->data.length);
c11_serializer__write_bytes(self, &checksum, sizeof(uint32_t));
return c11_vector__submit(&self->data, size);
}
void c11_deserializer__ctor(c11_deserializer* self, const void* data, int size){
self->data = (const uint8_t*)data;
self->size = size;
self->index = 0;
self->error_msg[0] = '\0';
}
void c11_deserializer__dtor(c11_deserializer* self){
// nothing to do
}
bool c11_deserializer__error(c11_deserializer* self, const char* msg){
snprintf(self->error_msg, sizeof(self->error_msg), "%s", msg);
return false;
}
void c11_deserializer__consume_mark(c11_deserializer* self, char expected) {
int8_t mark = c11_deserializer__read_i8(self);
if (mark != (int8_t)expected) {
c11__abort("internal error: deserialize mark mismatch: expected %c but got %c", expected, (char)mark);
}
}
bool c11_deserializer__check_header(c11_deserializer* self, int16_t magic, int8_t major_ver, int8_t minor_ver_min){
if(self->size < 8){
return c11_deserializer__error(self, "bad header: size < 8");
}
// read 16bit magic
int16_t file_magic = c11_deserializer__read_i16(self);
if(file_magic != magic){
return c11_deserializer__error(self, "bad header: magic mismatch");
}
// read 16bit version
self->major_ver = c11_deserializer__read_i8(self);
self->minor_ver = c11_deserializer__read_i8(self);
// check checksum
uint32_t checksum;
memcpy(&checksum, self->data + self->size - 4, sizeof(uint32_t));
uint32_t actual_checksum = c11__checksum_32bit(self->data, self->size - 4);
if(checksum != actual_checksum){
return c11_deserializer__error(self, "bad header: checksum mismatch");
}
// check version
if(self->major_ver != major_ver){
return c11_deserializer__error(self, "bad header: major version mismatch");
}
if(self->minor_ver < minor_ver_min){
// file_ver: 1.1, require_ver: 1.0 => ok
// file_ver: 1.1, require_ver: 1.1 => ok
// file_ver: 1.1, require_ver: 1.2 => error
return c11_deserializer__error(self, "bad header: minor version mismatch");
}
return true;
}
const char* c11_deserializer__read_cstr(c11_deserializer* self){
const char* p = (const char*)(self->data + self->index);
self->index += (strlen(p) + 1);
return p;
}
void* c11_deserializer__read_bytes(c11_deserializer* self, int size){
void* p = (void*)(self->data + self->index);
self->index += size;
return p;
}
// src/common\smallmap.c
#define SMALLMAP_T__SOURCE
#define K py_Name
#define V int
#define NAME c11_smallmap_n2d
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
#define SMALLMAP_T__SOURCE
#define K int
#define V int
#define NAME c11_smallmap_d2d
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
#define SMALLMAP_T__SOURCE
#define K c11_sv
#define V int
#define NAME c11_smallmap_v2d
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
#define SMALLMAP_T__SOURCE
#define K void*
#define V py_i64
#define NAME c11_smallmap_p2i
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
// src/common\socket.c
#if PK_ENABLE_OS
#include <stddef.h>
#if defined (_WIN32) || defined (_WIN64)
#include <WinSock2.h>
#include <ws2tcpip.h>
typedef SOCKET socket_fd;
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
typedef int socket_fd;
#endif
#define SOCKET_HANDLERTOFD(handler) (socket_fd)(uintptr_t)(handler)
#define SOCKET_FDTOHANDLER(fd) (c11_socket_handler)(uintptr_t)(fd)
static int c11_socket_init(){
#if defined (_WIN32) || defined (_WIN64)
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;
return WSAStartup(sockVersion, &wsaData);
#endif
return 0;
}
c11_socket_handler c11_socket_create(int family, int type, int protocol){
static int is_initialized = 0;
if(is_initialized == 0)
{
c11_socket_init();
is_initialized = 1;
}
return SOCKET_FDTOHANDLER(socket(family, type, protocol));
}
int c11_socket_bind(c11_socket_handler socket, const char* hostname, unsigned short port){
struct sockaddr_in bind_addr;
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(port);
inet_pton(AF_INET,hostname,&bind_addr.sin_addr);
if(bind(SOCKET_HANDLERTOFD(socket), (const struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1){
return -1;
}
return 0;
}
int c11_socket_listen(c11_socket_handler socket, int backlog){
listen(SOCKET_HANDLERTOFD(socket), backlog);
return 0;
}
c11_socket_handler c11_socket_accept(c11_socket_handler socket, char* client_ip, unsigned short* client_port){
struct sockaddr_in client_addr;
socklen_t sockaddr_len = sizeof(client_addr);
socket_fd client_socket = accept(SOCKET_HANDLERTOFD(socket), (struct sockaddr*)&client_addr, &sockaddr_len);
if(client_ip != NULL){
inet_ntop(AF_INET, &client_addr.sin_addr,client_ip,sizeof("255.255.255.255"));
}
if(client_port != NULL){
*client_port = ntohs(client_addr.sin_port);
}
return SOCKET_FDTOHANDLER(client_socket);
}
int c11_socket_connect(c11_socket_handler socket, const char* server_ip, unsigned short server_port){
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
if(connect(SOCKET_HANDLERTOFD(socket), (const struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
return -1;
}
return 0;
}
int c11_socket_recv(c11_socket_handler socket, char* buffer, int maxsize){
return recv(SOCKET_HANDLERTOFD(socket), buffer, maxsize,0);
}
int c11_socket_send(c11_socket_handler socket, const char* senddata, int datalen){
return send(SOCKET_HANDLERTOFD(socket), senddata, datalen, 0);
}
int c11_socket_close(c11_socket_handler socket){
#if defined (_WIN32) || defined (_WIN64)
return closesocket(SOCKET_HANDLERTOFD(socket));
#else
return close(SOCKET_HANDLERTOFD(socket));
#endif
}
int c11_socket_set_block(c11_socket_handler socket,int flag){
#if defined (_WIN32) || defined (_WIN64)
u_long mode = flag == 1 ? 0 : 1;
return ioctlsocket(SOCKET_HANDLERTOFD(socket), FIONBIO, &mode);
#else
int flags = fcntl(SOCKET_HANDLERTOFD(socket), F_GETFL, 0);
return fcntl(SOCKET_HANDLERTOFD(socket), F_SETFL, flags | O_NONBLOCK);
#endif
}
c11_socket_handler c11_socket_invalid_socket_handler(){
return (void*)(uintptr_t)(-1);
}
int c11_socket_get_last_error(){
#if defined (_WIN32) || defined (_WIN64)
return WSAGetLastError();
#else
return errno;
#endif
}
#undef SOCKET_HANDLERTOFD
#undef SOCKET_FDTOHANDLER
#endif // PK_ENABLE_OS
// src/common\sourcedata.c
#include <ctype.h>
#include <string.h>
static void SourceData__ctor(struct SourceData* self,
const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic) {
self->mode = mode;
self->is_dynamic = is_dynamic;
self->filename = c11_string__new(filename);
c11_vector__ctor(&self->line_starts, sizeof(const char*));
if(!source) {
self->source = NULL;
return;
}
// Skip utf8 BOM if there is any.
if(strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
// Drop all '\r'
c11_sbuf ss;
c11_sbuf__ctor(&ss);
while(true) {
char c = *source;
if(c == '\0') break;
if(c != '\r') c11_sbuf__write_char(&ss, c);
source++;
}
self->source = c11_sbuf__submit(&ss);
// remove trailing newline
int last_index = self->source->size - 1;
while(last_index >= 0 && isspace((unsigned char)self->source->data[last_index])) {
last_index--;
}
if(last_index >= 0) {
self->source->size = last_index + 1;
self->source->data[last_index + 1] = '\0';
}
c11_vector__push(const char*, &self->line_starts, self->source->data);
}
static void SourceData__dtor(struct SourceData* self) {
c11_string__delete(self->filename);
if(self->source) c11_string__delete(self->source);
c11_vector__dtor(&self->line_starts);
}
SourceData_ SourceData__rcnew(const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic) {
SourceData_ self = PK_MALLOC(sizeof(struct SourceData));
SourceData__ctor(self, source, filename, mode, is_dynamic);
self->rc.count = 1;
self->rc.dtor = (void (*)(void*))SourceData__dtor;
return self;
}
bool SourceData__get_line(const struct SourceData* self,
int lineno,
const char** st,
const char** ed) {
if(lineno < 0 || !self->source) return false;
lineno -= 1;
if(lineno < 0) lineno = 0;
const char* _start = c11__getitem(const char*, &self->line_starts, lineno);
const char* i = _start;
// max 300 chars
while(*i != '\n' && *i != '\0' && i - _start < 300)
i++;
*st = _start;
*ed = i;
return true;
}
void SourceData__snapshot(const struct SourceData* self,
c11_sbuf* ss,
int lineno,
const char* cursor,
const char* name) {
pk_sprintf(ss, " File \"%s\", line %d", self->filename->data, lineno);
if(name && *name) {
c11_sbuf__write_cstr(ss, ", in ");
c11_sbuf__write_cstr(ss, name);
}
const char *st = NULL, *ed;
if(SourceData__get_line(self, lineno, &st, &ed)) {
c11_sbuf__write_char(ss, '\n');
while(st < ed && isblank(*st))
++st;
if(st < ed) {
c11_sbuf__write_cstr(ss, " ");
c11_sbuf__write_cstrn(ss, st, ed - st);
if(cursor && st <= cursor && cursor <= ed) {
c11_sbuf__write_cstr(ss, "\n ");
for(int i = 0; i < (cursor - st); ++i)
c11_sbuf__write_char(ss, ' ');
c11_sbuf__write_cstr(ss, "^");
}
} else {
st = NULL;
}
}
// if(!st) { c11_sbuf__write_cstr(ss, " <?>"); }
}
// src/common\sstream.c
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
void c11_sbuf__ctor(c11_sbuf* self) {
c11_vector__ctor(&self->data, sizeof(char));
c11_vector__reserve(&self->data, sizeof(c11_string) + 64);
self->data.length = sizeof(c11_string);
}
void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); }
void c11_sbuf__write_char(c11_sbuf* self, char c) { c11_vector__push(char, &self->data, c); }
void c11_sbuf__write_pad(c11_sbuf* self, int count, char pad) {
for(int i = 0; i < count; i++) {
c11_sbuf__write_char(self, pad);
}
}
void c11_sbuf__write_int(c11_sbuf* self, int i) {
// len('-2147483648') == 11
c11_vector__reserve(&self->data, self->data.length + 11 + 1);
char* p = (char*)self->data.data + self->data.length;
int n = snprintf(p, 11 + 1, "%d", i);
self->data.length += n;
}
void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) {
// len('-9223372036854775808') == 20
c11_vector__reserve(&self->data, self->data.length + 20 + 1);
char* p = (char*)self->data.data + self->data.length;
int n = snprintf(p, 20 + 1, "%lld", (long long)val);
self->data.length += n;
}
void c11_sbuf__write_f64(c11_sbuf* self, double val, int precision) {
if(dmath_isinf(val)) {
c11_sbuf__write_cstr(self, val > 0 ? "inf" : "-inf");
return;
}
if(dmath_isnan(val)) {
c11_sbuf__write_cstr(self, "nan");
return;
}
char b[32];
int size;
if(precision < 0) {
int prec = 17 - 1; // std::numeric_limits<double>::max_digits10 == 17
size = snprintf(b, sizeof(b), "%.*g", prec, val);
} else {
int prec = precision;
size = snprintf(b, sizeof(b), "%.*f", prec, val);
}
c11_sbuf__write_cstr(self, b);
bool all_is_digit = true;
for(int i = 1; i < size; i++) {
if(!isdigit(b[i])) {
all_is_digit = false;
break;
}
}
if(all_is_digit) c11_sbuf__write_cstr(self, ".0");
}
void c11_sbuf__write_sv(c11_sbuf* self, c11_sv sv) {
c11_sbuf__write_cstrn(self, sv.data, sv.size);
}
void c11_sbuf__write_cstr(c11_sbuf* self, const char* str) {
c11_sbuf__write_cstrn(self, str, strlen(str));
}
void c11_sbuf__write_cstrn(c11_sbuf* self, const char* str, int n) {
c11_vector__extend(&self->data, str, n);
}
void c11_sbuf__write_quoted(c11_sbuf* self, c11_sv sv, char quote) {
assert(quote == '"' || quote == '\'');
c11_sbuf__write_char(self, quote);
for(int i = 0; i < sv.size; i++) {
char c = sv.data[i];
switch(c) {
case '"':
case '\'':
if(c == quote) c11_sbuf__write_char(self, '\\');
c11_sbuf__write_char(self, c);
break;
case '\\': c11_sbuf__write_cstrn(self, "\\\\", 2); break;
case '\n': c11_sbuf__write_cstrn(self, "\\n", 2); break;
case '\r': c11_sbuf__write_cstrn(self, "\\r", 2); break;
case '\t': c11_sbuf__write_cstrn(self, "\\t", 2); break;
case '\b': c11_sbuf__write_cstrn(self, "\\b", 2); break;
default: {
int u8bytes = c11__u8_header(c, true);
if(i + u8bytes > sv.size) u8bytes = 0; // invalid utf8
if(u8bytes <= 1) {
// not a valid utf8 char, or ascii
if(!isprint((unsigned char)c)) {
unsigned char uc = (unsigned char)c;
c11_sbuf__write_cstrn(self, "\\x", 2);
c11_sbuf__write_char(self, PK_HEX_TABLE[uc >> 4]);
c11_sbuf__write_char(self, PK_HEX_TABLE[uc & 0xf]);
} else {
c11_sbuf__write_char(self, c);
}
} else {
for(int j = 0; j < u8bytes; j++) {
c11_sbuf__write_char(self, sv.data[i + j]);
}
i += u8bytes - 1;
}
break;
}
}
}
c11_sbuf__write_char(self, quote);
}
void c11_sbuf__write_hex(c11_sbuf* self, unsigned char c, bool non_zero) {
unsigned char high = c >> 4;
unsigned char low = c & 0xf;
if(non_zero) {
if(high) c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
if(high || low) c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
} else {
c11_sbuf__write_char(self, PK_HEX_TABLE[high]);
c11_sbuf__write_char(self, PK_HEX_TABLE[low]);
}
}
void c11_sbuf__write_ptr(c11_sbuf* self, void* p) {
if(p == NULL) {
c11_sbuf__write_cstr(self, "0x0");
return;
}
c11_sbuf__write_cstr(self, "0x");
uintptr_t p_t = (uintptr_t)(p);
bool non_zero = true;
for(int i = sizeof(void*) - 1; i >= 0; i--) {
unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
c11_sbuf__write_hex(self, cpnt, non_zero);
if(cpnt != 0) non_zero = false;
}
}
c11_string* c11_sbuf__submit(c11_sbuf* self) {
c11_vector__push(char, &self->data, '\0');
int arr_length;
c11_string* retval = c11_vector__submit(&self->data, &arr_length);
retval->size = arr_length - sizeof(c11_string) - 1;
return retval;
}
void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out) {
c11_string* res = c11_sbuf__submit(self);
py_newstrv(out, (c11_sv){res->data, res->size});
c11_string__delete(res);
}
void pk_vsprintf(c11_sbuf* ss, const char* fmt, va_list args) {
while(*fmt) {
char c = *fmt;
if(c != '%') {
c11_sbuf__write_char(ss, c);
fmt++;
continue;
}
fmt++;
c = *fmt;
switch(c) {
case 'd': {
int i = va_arg(args, int);
c11_sbuf__write_int(ss, i);
break;
}
case 'i': {
int64_t i = va_arg(args, int64_t);
c11_sbuf__write_i64(ss, i);
break;
}
case 'f': {
double d = va_arg(args, double);
c11_sbuf__write_f64(ss, d, -1);
break;
}
case 's': {
const char* s = va_arg(args, const char*);
c11_sbuf__write_cstr(ss, s);
break;
}
case 'q': {
c11_sv sv = va_arg(args, c11_sv);
c11_sbuf__write_quoted(ss, sv, '\'');
break;
}
case 'Q': {
c11_sv sv = va_arg(args, c11_sv);
c11_sbuf__write_quoted(ss, sv, '"');
break;
}
case 'v': {
c11_sv sv = va_arg(args, c11_sv);
c11_sbuf__write_sv(ss, sv);
break;
}
case 'c': {
char c = va_arg(args, int);
c11_sbuf__write_char(ss, c);
break;
}
case 'p': {
void* p = va_arg(args, void*);
c11_sbuf__write_ptr(ss, p);
break;
}
case 't': {
py_Type t = va_arg(args, int);
c11_sbuf__write_cstr(ss, py_tpname(t));
break;
}
case 'n': {
py_Name n = va_arg(args, void*);
c11_sbuf__write_cstr(ss, py_name2str(n));
break;
}
case '%': c11_sbuf__write_char(ss, '%'); break;
default:
c11_sbuf__write_char(ss, c);
assert(false); // invalid format
break;
}
fmt++;
}
}
void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
pk_vsprintf(ss, fmt, args);
va_end(args);
}
// src/common\str.c
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
c11_string* c11_string__new(const char* data) { return c11_string__new2(data, strlen(data)); }
c11_string* c11_string__new2(const char* data, int size) {
c11_string* retval = PK_MALLOC(sizeof(c11_string) + size + 1);
c11_string__ctor2(retval, data, size);
return retval;
}
c11_string* c11_string__new3(const char* fmt, ...) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
va_list args;
va_start(args, fmt);
// c11_sbuf__write_vfmt(&buf, fmt, args);
pk_vsprintf(&buf, fmt, args);
va_end(args);
return c11_sbuf__submit(&buf);
}
void c11_string__ctor(c11_string* self, const char* data) {
c11_string__ctor2(self, data, strlen(data));
}
void c11_string__ctor2(c11_string* self, const char* data, int size) {
self->size = size;
char* p = (char*)self->data;
memcpy(p, data, size);
p[size] = '\0';
}
void c11_string__ctor3(c11_string* self, int size) {
self->size = size;
char* p = (char*)self->data;
p[size] = '\0';
}
c11_string* c11_string__copy(c11_string* self) {
int total_size = sizeof(c11_string) + self->size + 1;
c11_string* retval = PK_MALLOC(total_size);
memcpy(retval, self, total_size);
return retval;
}
void c11_string__delete(c11_string* self) { PK_FREE(self); }
c11_sv c11_string__sv(c11_string* self) { return (c11_sv){self->data, self->size}; }
c11_string* c11_sv__replace(c11_sv self, char old, char new_) {
c11_string* retval = c11_string__new2(self.data, self.size);
char* p = (char*)retval->data;
for(int i = 0; i < retval->size; i++) {
if(p[i] == old) p[i] = new_;
}
return retval;
}
c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
int start = 0;
while(true) {
int i = c11_sv__index2(self, old, start);
if(i == -1) break;
c11_sv tmp = c11_sv__slice2(self, start, i);
c11_sbuf__write_sv(&buf, tmp);
c11_sbuf__write_sv(&buf, new_);
start = i + old.size;
}
c11_sv tmp = c11_sv__slice2(self, start, self.size);
c11_sbuf__write_sv(&buf, tmp);
return c11_sbuf__submit(&buf);
}
int c11_sv__u8_length(c11_sv sv) { return c11__byte_index_to_unicode(sv.data, sv.size); }
c11_sv c11_sv__u8_getitem(c11_sv sv, int i) {
i = c11__unicode_index_to_byte(sv.data, i);
int size = c11__u8_header(sv.data[i], false);
return c11_sv__slice2(sv, i, i + size);
}
c11_string* c11_sv__u8_slice(c11_sv sv, int start, int stop, int step) {
c11_sbuf ss;
c11_sbuf__ctor(&ss);
assert(step != 0);
for(int i = start; step > 0 ? i < stop : i > stop; i += step) {
c11_sv unicode = c11_sv__u8_getitem(sv, i);
c11_sbuf__write_sv(&ss, unicode);
}
return c11_sbuf__submit(&ss);
}
/////////////////////////////////////////
c11_sv c11_sv__slice(c11_sv sv, int start) { return c11_sv__slice2(sv, start, sv.size); }
c11_sv c11_sv__slice2(c11_sv sv, int start, int stop) {
if(start < 0) start = 0;
if(stop < start) stop = start;
if(stop > sv.size) stop = sv.size;
return (c11_sv){sv.data + start, stop - start};
}
c11_sv c11_sv__strip(c11_sv sv, c11_sv chars, bool left, bool right) {
int L = 0;
int R = c11_sv__u8_length(sv);
if(left) {
while(L < R) {
c11_sv tmp = c11_sv__u8_getitem(sv, L);
bool found = c11_sv__index2(chars, tmp, 0) != -1;
if(!found) break;
L++;
}
}
if(right) {
while(L < R) {
c11_sv tmp = c11_sv__u8_getitem(sv, R - 1);
bool found = c11_sv__index2(chars, tmp, 0) != -1;
if(!found) break;
R--;
}
}
int start = c11__unicode_index_to_byte(sv.data, L);
int stop = c11__unicode_index_to_byte(sv.data, R);
return c11_sv__slice2(sv, start, stop);
}
int c11_sv__index(c11_sv self, char c) {
for(int i = 0; i < self.size; i++) {
if(self.data[i] == c) return i;
}
return -1;
}
int c11_sv__rindex(c11_sv self, char c) {
for(int i = self.size - 1; i >= 0; i--) {
if(self.data[i] == c) return i;
}
return -1;
}
c11_sv c11_sv__filename(c11_sv self) {
int sep_index_1 = c11_sv__rindex(self, '/');
int sep_index_2 = c11_sv__rindex(self, '\\');
int sep_index = c11__max(sep_index_1, sep_index_2);
if(sep_index == -1) return self;
return c11_sv__slice(self, sep_index + 1);
}
int c11_sv__index2(c11_sv self, c11_sv sub, int start) {
if(sub.size == 0) return start;
int max_end = self.size - sub.size;
for(int i = start; i <= max_end; i++) {
int res = memcmp(self.data + i, sub.data, sub.size);
if(res == 0) return i;
}
return -1;
}
int c11_sv__count(c11_sv self, c11_sv sub) {
if(sub.size == 0) return self.size + 1;
int cnt = 0;
int start = 0;
while(true) {
int i = c11_sv__index2(self, sub, start);
if(i == -1) break;
cnt++;
start = i + sub.size;
}
return cnt;
}
bool c11_sv__startswith(c11_sv self, c11_sv prefix) {
if(prefix.size > self.size) return false;
return memcmp(self.data, prefix.data, prefix.size) == 0;
}
bool c11_sv__endswith(c11_sv self, c11_sv suffix) {
if(suffix.size > self.size) return false;
return memcmp(self.data + self.size - suffix.size, suffix.data, suffix.size) == 0;
}
uint64_t c11_sv__hash(c11_sv self) {
uint64_t hash = 5381;
for(int i = 0; i < self.size; i++) {
// hash * 33 + c
hash = ((hash << 5) + hash) + (unsigned char)self.data[i];
}
return hash;
}
c11_vector /* T=c11_sv */ c11_sv__splitwhitespace(c11_sv self) {
c11_vector retval;
c11_vector__ctor(&retval, sizeof(c11_sv));
const char* data = self.data;
int i = 0;
for(int j = 0; j < self.size; j++) {
if(isspace(data[j])) {
assert(j >= i);
c11_sv tmp = {data + i, j - i};
c11_vector__push(c11_sv, &retval, tmp);
i = j + 1;
}
}
if(i <= self.size) {
c11_sv tmp = {data + i, self.size - i};
c11_vector__push(c11_sv, &retval, tmp);
}
return retval;
}
c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep) {
c11_vector retval;
c11_vector__ctor(&retval, sizeof(c11_sv));
const char* data = self.data;
int i = 0;
for(int j = 0; j < self.size; j++) {
if(data[j] == sep) {
assert(j >= i);
c11_sv tmp = {data + i, j - i};
c11_vector__push(c11_sv, &retval, tmp);
i = j + 1;
}
}
if(i <= self.size) {
c11_sv tmp = {data + i, self.size - i};
c11_vector__push(c11_sv, &retval, tmp);
}
return retval;
}
c11_vector /* T=c11_sv */ c11_sv__split2(c11_sv self, c11_sv sep) {
if(sep.size == 1) return c11_sv__split(self, sep.data[0]);
c11_vector retval;
c11_vector__ctor(&retval, sizeof(c11_sv));
int start = 0;
const char* data = self.data;
while(true) {
int i = c11_sv__index2(self, sep, start);
if(i == -1) break;
c11_sv tmp = {data + start, i - start};
c11_vector__push(c11_sv, &retval, tmp);
start = i + sep.size;
}
c11_sv tmp = {data + start, self.size - start};
c11_vector__push(c11_sv, &retval, tmp);
return retval;
}
int c11__unicode_index_to_byte(const char* data, int i) {
int j = 0;
while(i > 0) {
j += c11__u8_header(data[j], false);
i--;
}
return j;
}
int c11__byte_index_to_unicode(const char* data, int n) {
int cnt = 0;
for(int i = 0; i < n; i++) {
if((data[i] & 0xC0) != 0x80) cnt++;
}
return cnt;
}
//////////////
bool c11_bytes__eq(c11_bytes* self, c11_bytes* other) {
if(self->size != other->size) return false;
return memcmp(self->data, other->data, self->size) == 0;
}
int c11_sv__cmp(c11_sv self, c11_sv other) {
int res = strncmp(self.data, other.data, c11__min(self.size, other.size));
if(res != 0) return res;
return self.size - other.size;
}
int c11_sv__cmp2(c11_sv self, const char* other) {
int size = strlen(other);
int res = strncmp(self.data, other, c11__min(self.size, size));
if(res != 0) return res;
return self.size - size;
}
bool c11__streq(const char* a, const char* b) { return strcmp(a, b) == 0; }
bool c11__sveq(c11_sv a, c11_sv b) {
if(a.size != b.size) return false;
return memcmp(a.data, b.data, a.size) == 0;
}
bool c11__sveq2(c11_sv a, const char* b) {
int size = strlen(b);
if(a.size != size) return false;
return memcmp(a.data, b, size) == 0;
}
int c11__u8_header(unsigned char c, bool suppress) {
if((c & 0b10000000) == 0) return 1;
if((c & 0b11100000) == 0b11000000) return 2;
if((c & 0b11110000) == 0b11100000) return 3;
if((c & 0b11111000) == 0b11110000) return 4;
if((c & 0b11111100) == 0b11111000) return 5;
if((c & 0b11111110) == 0b11111100) return 6;
if(!suppress) c11__abort("invalid utf8 char");
return 0;
}
int c11__u8_value(int u8bytes, const char* data) {
assert(u8bytes != 0);
if(u8bytes == 1) return (int)data[0];
uint32_t value = 0;
for(int k = 0; k < u8bytes; k++) {
uint8_t b = data[k];
if(k == 0) {
if(u8bytes == 2)
value = (b & 0b00011111) << 6;
else if(u8bytes == 3)
value = (b & 0b00001111) << 12;
else if(u8bytes == 4)
value = (b & 0b00000111) << 18;
} else {
value |= (b & 0b00111111) << (6 * (u8bytes - k - 1));
}
}
return (int)value;
}
int c11__u32_to_u8(uint32_t utf32_char, char utf8_output[4]) {
int length = 0;
if(utf32_char <= 0x7F) {
// 1-byte UTF-8
utf8_output[0] = (char)utf32_char;
length = 1;
} else if(utf32_char <= 0x7FF) {
// 2-byte UTF-8
utf8_output[0] = (char)(0xC0 | ((utf32_char >> 6) & 0x1F));
utf8_output[1] = (char)(0x80 | (utf32_char & 0x3F));
length = 2;
} else if(utf32_char <= 0xFFFF) {
// 3-byte UTF-8
utf8_output[0] = (char)(0xE0 | ((utf32_char >> 12) & 0x0F));
utf8_output[1] = (char)(0x80 | ((utf32_char >> 6) & 0x3F));
utf8_output[2] = (char)(0x80 | (utf32_char & 0x3F));
length = 3;
} else if(utf32_char <= 0x10FFFF) {
// 4-byte UTF-8
utf8_output[0] = (char)(0xF0 | ((utf32_char >> 18) & 0x07));
utf8_output[1] = (char)(0x80 | ((utf32_char >> 12) & 0x3F));
utf8_output[2] = (char)(0x80 | ((utf32_char >> 6) & 0x3F));
utf8_output[3] = (char)(0x80 | (utf32_char & 0x3F));
length = 4;
} else {
// Invalid UTF-32 character
return -1;
}
return length;
}
char* c11_strdup(const char* str) {
int len = strlen(str);
char* dst = PK_MALLOC(len + 1);
memcpy(dst, str, len);
dst[len] = '\0';
return dst;
}
unsigned char* c11_memdup(const unsigned char* src, int size) {
unsigned char* dst = PK_MALLOC(size);
memcpy(dst, src, size);
return dst;
}
IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
*out = 0;
c11_sv prefix = {.data = text.data, .size = c11__min(2, text.size)};
if(base == -1) {
if(c11__sveq2(prefix, "0b"))
base = 2;
else if(c11__sveq2(prefix, "0o"))
base = 8;
else if(c11__sveq2(prefix, "0x"))
base = 16;
else
base = 10;
}
if(base == 10) {
// 10-base 12334
if(text.size == 0) return IntParsing_FAILURE;
for(int i = 0; i < text.size; i++) {
char c = text.data[i];
if(c >= '0' && c <= '9') {
*out = (*out * 10) + (c - '0');
} else {
return IntParsing_FAILURE;
}
}
// "9223372036854775807".__len__() == 19
if(text.size > 19) return IntParsing_OVERFLOW;
return IntParsing_SUCCESS;
} else if(base == 2) {
// 2-base 0b101010
if(c11__sveq2(prefix, "0b")) {
// text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2};
}
if(text.size == 0) return IntParsing_FAILURE;
for(int i = 0; i < text.size; i++) {
char c = text.data[i];
if(c == '0' || c == '1') {
*out = (*out << 1) | (c - '0');
} else {
return IntParsing_FAILURE;
}
}
// "111111111111111111111111111111111111111111111111111111111111111".__len__() == 63
if(text.size > 63) return IntParsing_OVERFLOW;
return IntParsing_SUCCESS;
} else if(base == 8) {
// 8-base 0o123
if(c11__sveq2(prefix, "0o")) {
// text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2};
}
if(text.size == 0) return IntParsing_FAILURE;
for(int i = 0; i < text.size; i++) {
char c = text.data[i];
if(c >= '0' && c <= '7') {
*out = (*out << 3) | (c - '0');
} else {
return IntParsing_FAILURE;
}
}
// "777777777777777777777".__len__() == 21
if(text.size > 21) return IntParsing_OVERFLOW;
return IntParsing_SUCCESS;
} else if(base == 16) {
// 16-base 0x123
if(c11__sveq2(prefix, "0x")) {
// text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2};
}
if(text.size == 0) return IntParsing_FAILURE;
for(int i = 0; i < text.size; i++) {
char c = text.data[i];
if(c >= '0' && c <= '9') {
*out = (*out << 4) | (c - '0');
} else if(c >= 'a' && c <= 'f') {
*out = (*out << 4) | (c - 'a' + 10);
} else if(c >= 'A' && c <= 'F') {
*out = (*out << 4) | (c - 'A' + 10);
} else {
return IntParsing_FAILURE;
}
}
// "7fffffffffffffff".__len__() == 16
if(text.size > 16) return IntParsing_OVERFLOW;
return IntParsing_SUCCESS;
}
return IntParsing_FAILURE;
}
const char* c11__search_u32_ranges(int c, const c11_u32_range* p, int n_ranges) {
int lbound = 0;
int ubound = n_ranges - 1;
if(c < p[0].start || c > p[ubound].end) return NULL;
while(ubound >= lbound) {
int mid = (lbound + ubound) / 2;
if(c > p[mid].end) {
lbound = mid + 1;
} else if(c < p[mid].start) {
ubound = mid - 1;
} else {
return p[mid].data;
}
}
return NULL;
}
// clang-format off
const static c11_u32_range kLoRanges[] = {
{ 170, 170 },
{ 186, 186 },
{ 443, 443 },
{ 448, 451 },
{ 660, 660 },
{ 1488, 1514 },
{ 1519, 1522 },
{ 1568, 1599 },
{ 1601, 1610 },
{ 1646, 1647 },
{ 1649, 1747 },
{ 1749, 1749 },
{ 1774, 1775 },
{ 1786, 1788 },
{ 1791, 1791 },
{ 1808, 1808 },
{ 1810, 1839 },
{ 1869, 1957 },
{ 1969, 1969 },
{ 1994, 2026 },
{ 2048, 2069 },
{ 2112, 2136 },
{ 2144, 2154 },
{ 2160, 2183 },
{ 2185, 2190 },
{ 2208, 2248 },
{ 2308, 2361 },
{ 2365, 2365 },
{ 2384, 2384 },
{ 2392, 2401 },
{ 2418, 2432 },
{ 2437, 2444 },
{ 2447, 2448 },
{ 2451, 2472 },
{ 2474, 2480 },
{ 2482, 2482 },
{ 2486, 2489 },
{ 2493, 2493 },
{ 2510, 2510 },
{ 2524, 2525 },
{ 2527, 2529 },
{ 2544, 2545 },
{ 2556, 2556 },
{ 2565, 2570 },
{ 2575, 2576 },
{ 2579, 2600 },
{ 2602, 2608 },
{ 2610, 2611 },
{ 2613, 2614 },
{ 2616, 2617 },
{ 2649, 2652 },
{ 2654, 2654 },
{ 2674, 2676 },
{ 2693, 2701 },
{ 2703, 2705 },
{ 2707, 2728 },
{ 2730, 2736 },
{ 2738, 2739 },
{ 2741, 2745 },
{ 2749, 2749 },
{ 2768, 2768 },
{ 2784, 2785 },
{ 2809, 2809 },
{ 2821, 2828 },
{ 2831, 2832 },
{ 2835, 2856 },
{ 2858, 2864 },
{ 2866, 2867 },
{ 2869, 2873 },
{ 2877, 2877 },
{ 2908, 2909 },
{ 2911, 2913 },
{ 2929, 2929 },
{ 2947, 2947 },
{ 2949, 2954 },
{ 2958, 2960 },
{ 2962, 2965 },
{ 2969, 2970 },
{ 2972, 2972 },
{ 2974, 2975 },
{ 2979, 2980 },
{ 2984, 2986 },
{ 2990, 3001 },
{ 3024, 3024 },
{ 3077, 3084 },
{ 3086, 3088 },
{ 3090, 3112 },
{ 3114, 3129 },
{ 3133, 3133 },
{ 3160, 3162 },
{ 3165, 3165 },
{ 3168, 3169 },
{ 3200, 3200 },
{ 3205, 3212 },
{ 3214, 3216 },
{ 3218, 3240 },
{ 3242, 3251 },
{ 3253, 3257 },
{ 3261, 3261 },
{ 3293, 3294 },
{ 3296, 3297 },
{ 3313, 3314 },
{ 3332, 3340 },
{ 3342, 3344 },
{ 3346, 3386 },
{ 3389, 3389 },
{ 3406, 3406 },
{ 3412, 3414 },
{ 3423, 3425 },
{ 3450, 3455 },
{ 3461, 3478 },
{ 3482, 3505 },
{ 3507, 3515 },
{ 3517, 3517 },
{ 3520, 3526 },
{ 3585, 3632 },
{ 3634, 3635 },
{ 3648, 3653 },
{ 3713, 3714 },
{ 3716, 3716 },
{ 3718, 3722 },
{ 3724, 3747 },
{ 3749, 3749 },
{ 3751, 3760 },
{ 3762, 3763 },
{ 3773, 3773 },
{ 3776, 3780 },
{ 3804, 3807 },
{ 3840, 3840 },
{ 3904, 3911 },
{ 3913, 3948 },
{ 3976, 3980 },
{ 4096, 4138 },
{ 4159, 4159 },
{ 4176, 4181 },
{ 4186, 4189 },
{ 4193, 4193 },
{ 4197, 4198 },
{ 4206, 4208 },
{ 4213, 4225 },
{ 4238, 4238 },
{ 4352, 4680 },
{ 4682, 4685 },
{ 4688, 4694 },
{ 4696, 4696 },
{ 4698, 4701 },
{ 4704, 4744 },
{ 4746, 4749 },
{ 4752, 4784 },
{ 4786, 4789 },
{ 4792, 4798 },
{ 4800, 4800 },
{ 4802, 4805 },
{ 4808, 4822 },
{ 4824, 4880 },
{ 4882, 4885 },
{ 4888, 4954 },
{ 4992, 5007 },
{ 5121, 5740 },
{ 5743, 5759 },
{ 5761, 5786 },
{ 5792, 5866 },
{ 5873, 5880 },
{ 5888, 5905 },
{ 5919, 5937 },
{ 5952, 5969 },
{ 5984, 5996 },
{ 5998, 6000 },
{ 6016, 6067 },
{ 6108, 6108 },
{ 6176, 6210 },
{ 6212, 6264 },
{ 6272, 6276 },
{ 6279, 6312 },
{ 6314, 6314 },
{ 6320, 6389 },
{ 6400, 6430 },
{ 6480, 6509 },
{ 6512, 6516 },
{ 6528, 6571 },
{ 6576, 6601 },
{ 6656, 6678 },
{ 6688, 6740 },
{ 6917, 6963 },
{ 6981, 6988 },
{ 7043, 7072 },
{ 7086, 7087 },
{ 7098, 7141 },
{ 7168, 7203 },
{ 7245, 7247 },
{ 7258, 7287 },
{ 7401, 7404 },
{ 7406, 7411 },
{ 7413, 7414 },
{ 7418, 7418 },
{ 8501, 8504 },
{ 11568, 11623 },
{ 11648, 11670 },
{ 11680, 11686 },
{ 11688, 11694 },
{ 11696, 11702 },
{ 11704, 11710 },
{ 11712, 11718 },
{ 11720, 11726 },
{ 11728, 11734 },
{ 11736, 11742 },
{ 12294, 12294 },
{ 12348, 12348 },
{ 12353, 12438 },
{ 12447, 12447 },
{ 12449, 12538 },
{ 12543, 12543 },
{ 12549, 12591 },
{ 12593, 12686 },
{ 12704, 12735 },
{ 12784, 12799 },
{ 13312, 19903 },
{ 19968, 40980 },
{ 40982, 42124 },
{ 42192, 42231 },
{ 42240, 42507 },
{ 42512, 42527 },
{ 42538, 42539 },
{ 42606, 42606 },
{ 42656, 42725 },
{ 42895, 42895 },
{ 42999, 42999 },
{ 43003, 43009 },
{ 43011, 43013 },
{ 43015, 43018 },
{ 43020, 43042 },
{ 43072, 43123 },
{ 43138, 43187 },
{ 43250, 43255 },
{ 43259, 43259 },
{ 43261, 43262 },
{ 43274, 43301 },
{ 43312, 43334 },
{ 43360, 43388 },
{ 43396, 43442 },
{ 43488, 43492 },
{ 43495, 43503 },
{ 43514, 43518 },
{ 43520, 43560 },
{ 43584, 43586 },
{ 43588, 43595 },
{ 43616, 43631 },
{ 43633, 43638 },
{ 43642, 43642 },
{ 43646, 43695 },
{ 43697, 43697 },
{ 43701, 43702 },
{ 43705, 43709 },
{ 43712, 43712 },
{ 43714, 43714 },
{ 43739, 43740 },
{ 43744, 43754 },
{ 43762, 43762 },
{ 43777, 43782 },
{ 43785, 43790 },
{ 43793, 43798 },
{ 43808, 43814 },
{ 43816, 43822 },
{ 43968, 44002 },
{ 44032, 55203 },
{ 55216, 55238 },
{ 55243, 55291 },
{ 63744, 64109 },
{ 64112, 64217 },
{ 64285, 64285 },
{ 64287, 64296 },
{ 64298, 64310 },
{ 64312, 64316 },
{ 64318, 64318 },
{ 64320, 64321 },
{ 64323, 64324 },
{ 64326, 64433 },
{ 64467, 64829 },
{ 64848, 64911 },
{ 64914, 64967 },
{ 65008, 65019 },
{ 65136, 65140 },
{ 65142, 65276 },
{ 65382, 65391 },
{ 65393, 65437 },
{ 65440, 65470 },
{ 65474, 65479 },
{ 65482, 65487 },
{ 65490, 65495 },
{ 65498, 65500 },
{ 65536, 65547 },
{ 65549, 65574 },
{ 65576, 65594 },
{ 65596, 65597 },
{ 65599, 65613 },
{ 65616, 65629 },
{ 65664, 65786 },
{ 66176, 66204 },
{ 66208, 66256 },
{ 66304, 66335 },
{ 66349, 66368 },
{ 66370, 66377 },
{ 66384, 66421 },
{ 66432, 66461 },
{ 66464, 66499 },
{ 66504, 66511 },
{ 66640, 66717 },
{ 66816, 66855 },
{ 66864, 66915 },
{ 67072, 67382 },
{ 67392, 67413 },
{ 67424, 67431 },
{ 67584, 67589 },
{ 67592, 67592 },
{ 67594, 67637 },
{ 67639, 67640 },
{ 67644, 67644 },
{ 67647, 67669 },
{ 67680, 67702 },
{ 67712, 67742 },
{ 67808, 67826 },
{ 67828, 67829 },
{ 67840, 67861 },
{ 67872, 67897 },
{ 67968, 68023 },
{ 68030, 68031 },
{ 68096, 68096 },
{ 68112, 68115 },
{ 68117, 68119 },
{ 68121, 68149 },
{ 68192, 68220 },
{ 68224, 68252 },
{ 68288, 68295 },
{ 68297, 68324 },
{ 68352, 68405 },
{ 68416, 68437 },
{ 68448, 68466 },
{ 68480, 68497 },
{ 68608, 68680 },
{ 68864, 68899 },
{ 69248, 69289 },
{ 69296, 69297 },
{ 69376, 69404 },
{ 69415, 69415 },
{ 69424, 69445 },
{ 69488, 69505 },
{ 69552, 69572 },
{ 69600, 69622 },
{ 69635, 69687 },
{ 69745, 69746 },
{ 69749, 69749 },
{ 69763, 69807 },
{ 69840, 69864 },
{ 69891, 69926 },
{ 69956, 69956 },
{ 69959, 69959 },
{ 69968, 70002 },
{ 70006, 70006 },
{ 70019, 70066 },
{ 70081, 70084 },
{ 70106, 70106 },
{ 70108, 70108 },
{ 70144, 70161 },
{ 70163, 70187 },
{ 70272, 70278 },
{ 70280, 70280 },
{ 70282, 70285 },
{ 70287, 70301 },
{ 70303, 70312 },
{ 70320, 70366 },
{ 70405, 70412 },
{ 70415, 70416 },
{ 70419, 70440 },
{ 70442, 70448 },
{ 70450, 70451 },
{ 70453, 70457 },
{ 70461, 70461 },
{ 70480, 70480 },
{ 70493, 70497 },
{ 70656, 70708 },
{ 70727, 70730 },
{ 70751, 70753 },
{ 70784, 70831 },
{ 70852, 70853 },
{ 70855, 70855 },
{ 71040, 71086 },
{ 71128, 71131 },
{ 71168, 71215 },
{ 71236, 71236 },
{ 71296, 71338 },
{ 71352, 71352 },
{ 71424, 71450 },
{ 71488, 71494 },
{ 71680, 71723 },
{ 71935, 71942 },
{ 71945, 71945 },
{ 71948, 71955 },
{ 71957, 71958 },
{ 71960, 71983 },
{ 71999, 71999 },
{ 72001, 72001 },
{ 72096, 72103 },
{ 72106, 72144 },
{ 72161, 72161 },
{ 72163, 72163 },
{ 72192, 72192 },
{ 72203, 72242 },
{ 72250, 72250 },
{ 72272, 72272 },
{ 72284, 72329 },
{ 72349, 72349 },
{ 72368, 72440 },
{ 72704, 72712 },
{ 72714, 72750 },
{ 72768, 72768 },
{ 72818, 72847 },
{ 72960, 72966 },
{ 72968, 72969 },
{ 72971, 73008 },
{ 73030, 73030 },
{ 73056, 73061 },
{ 73063, 73064 },
{ 73066, 73097 },
{ 73112, 73112 },
{ 73440, 73458 },
{ 73648, 73648 },
{ 73728, 74649 },
{ 74880, 75075 },
{ 77712, 77808 },
{ 77824, 78894 },
{ 82944, 83526 },
{ 92160, 92728 },
{ 92736, 92766 },
{ 92784, 92862 },
{ 92880, 92909 },
{ 92928, 92975 },
{ 93027, 93047 },
{ 93053, 93071 },
{ 93952, 94026 },
{ 94032, 94032 },
{ 94208, 100343 },
{ 100352, 101589 },
{ 101632, 101640 },
{ 110592, 110882 },
{ 110928, 110930 },
{ 110948, 110951 },
{ 110960, 111355 },
{ 113664, 113770 },
{ 113776, 113788 },
{ 113792, 113800 },
{ 113808, 113817 },
{ 122634, 122634 },
{ 123136, 123180 },
{ 123214, 123214 },
{ 123536, 123565 },
{ 123584, 123627 },
{ 124896, 124902 },
{ 124904, 124907 },
{ 124909, 124910 },
{ 124912, 124926 },
{ 124928, 125124 },
{ 126464, 126467 },
{ 126469, 126495 },
{ 126497, 126498 },
{ 126500, 126500 },
{ 126503, 126503 },
{ 126505, 126514 },
{ 126516, 126519 },
{ 126521, 126521 },
{ 126523, 126523 },
{ 126530, 126530 },
{ 126535, 126535 },
{ 126537, 126537 },
{ 126539, 126539 },
{ 126541, 126543 },
{ 126545, 126546 },
{ 126548, 126548 },
{ 126551, 126551 },
{ 126553, 126553 },
{ 126555, 126555 },
{ 126557, 126557 },
{ 126559, 126559 },
{ 126561, 126562 },
{ 126564, 126564 },
{ 126567, 126570 },
{ 126572, 126578 },
{ 126580, 126583 },
{ 126585, 126588 },
{ 126590, 126590 },
{ 126592, 126601 },
{ 126603, 126619 },
{ 126625, 126627 },
{ 126629, 126633 },
{ 126635, 126651 },
{ 131072, 173791 },
{ 173824, 177976 },
{ 177984, 178205 },
{ 178208, 183969 },
{ 183984, 191456 },
{ 194560, 195101 },
{ 196608, 201546 },
};
// clang-format on
bool c11__is_unicode_Lo_char(int c) {
if(c == 0x1f955) return true;
const char* data =
c11__search_u32_ranges(c, kLoRanges, sizeof(kLoRanges) / sizeof(c11_u32_range));
return data != NULL;
}
// src/common\threads.c
#include <stdarg.h>
#if PK_ENABLE_THREADS
#if PK_USE_PTHREADS
bool c11_thrd__create(c11_thrd_t* thrd, c11_thrd_func_t func, void* arg) {
int res = pthread_create(thrd, NULL, func, arg);
return res == 0;
}
void c11_thrd__yield() { sched_yield(); }
void c11_thrd__join(c11_thrd_t thrd) { pthread_join(thrd, NULL); }
c11_thrd_t c11_thrd__current() { return pthread_self(); }
bool c11_thrd__equal(c11_thrd_t a, c11_thrd_t b) { return pthread_equal(a, b); }
void c11_mutex__ctor(c11_mutex_t* mutex) { pthread_mutex_init(mutex, NULL); }
void c11_mutex__dtor(c11_mutex_t* mutex) { pthread_mutex_destroy(mutex); }
void c11_mutex__lock(c11_mutex_t* mutex) { pthread_mutex_lock(mutex); }
void c11_mutex__unlock(c11_mutex_t* mutex) { pthread_mutex_unlock(mutex); }
void c11_cond__ctor(c11_cond_t* cond) { pthread_cond_init(cond, NULL); }
void c11_cond__dtor(c11_cond_t* cond) { pthread_cond_destroy(cond); }
void c11_cond__wait(c11_cond_t* cond, c11_mutex_t* mutex) { pthread_cond_wait(cond, mutex); }
void c11_cond__signal(c11_cond_t* cond) { pthread_cond_signal(cond); }
void c11_cond__broadcast(c11_cond_t* cond) { pthread_cond_broadcast(cond); }
#else
bool c11_thrd__create(c11_thrd_t* thrd, c11_thrd_func_t func, void* arg) {
int res = thrd_create(thrd, func, arg);
return res == thrd_success;
}
void c11_thrd__yield() { thrd_yield(); }
void c11_thrd__join(c11_thrd_t thrd) { thrd_join(thrd, NULL); }
c11_thrd_t c11_thrd__current() { return thrd_current(); }
bool c11_thrd__equal(c11_thrd_t a, c11_thrd_t b) { return thrd_equal(a, b); }
void c11_mutex__ctor(c11_mutex_t* mutex) { mtx_init(mutex, mtx_plain); }
void c11_mutex__dtor(c11_mutex_t* mutex) { mtx_destroy(mutex); }
void c11_mutex__lock(c11_mutex_t* mutex) { mtx_lock(mutex); }
void c11_mutex__unlock(c11_mutex_t* mutex) { mtx_unlock(mutex); }
void c11_cond__ctor(c11_cond_t* cond) { cnd_init(cond); }
void c11_cond__dtor(c11_cond_t* cond) { cnd_destroy(cond); }
void c11_cond__wait(c11_cond_t* cond, c11_mutex_t* mutex) { cnd_wait(cond, mutex); }
void c11_cond__signal(c11_cond_t* cond) { cnd_signal(cond); }
void c11_cond__broadcast(c11_cond_t* cond) { cnd_broadcast(cond); }
#endif
#define C11_THRDPOOL_DEBUG 0
#if C11_THRDPOOL_DEBUG
static void c11_thrdpool_debug_log(int index, const char* format, ...) {
va_list args;
va_start(args, format);
char buf[512];
int n = sprintf(buf, "[%.6f - Worker %2d] ", time_ns() / 1e9, index);
vsprintf(buf + n, format, args);
printf("%s\n", buf);
va_end(args);
}
#else
#define c11_thrdpool_debug_log(...) \
do { \
} while(0)
#endif
static c11_thrd_retval_t _thrdpool_worker(void* arg) {
c11_thrdpool_worker* p_worker = (c11_thrdpool_worker*)arg;
c11_thrdpool_tasks* p_tasks = p_worker->p_tasks;
while(true) {
c11_thrdpool_debug_log(p_worker->index, "Waiting for mutex lock...");
c11_mutex__lock(p_worker->p_mutex);
atomic_fetch_add_explicit(p_worker->p_ready_workers_num, 1, memory_order_relaxed);
c11_thrdpool_debug_log(p_worker->index, "Mutex locked, checking for tasks...");
if(atomic_load_explicit(&p_tasks->sync_val, memory_order_relaxed) == -1) {
c11_mutex__unlock(p_worker->p_mutex);
return 0; // force kill
}
while(true) {
c11_cond__wait(p_worker->p_cond, p_worker->p_mutex);
int sync_val = atomic_load_explicit(&p_tasks->sync_val, memory_order_relaxed);
c11_thrdpool_debug_log(p_worker->index,
"Woke up from condition variable, sync_val=%d",
sync_val);
if(sync_val == 1) break;
if(sync_val == -1) {
c11_mutex__unlock(p_worker->p_mutex);
return 0; // force kill
}
}
atomic_fetch_sub_explicit(p_worker->p_ready_workers_num, 1, memory_order_relaxed);
c11_mutex__unlock(p_worker->p_mutex);
c11_thrdpool_debug_log(p_worker->index, "Received tasks, starting execution...");
// execute tasks
int completed_count = 0;
while(true) {
int arg_index =
atomic_fetch_add_explicit(&p_tasks->current_index, 1, memory_order_relaxed);
if(arg_index < p_tasks->length) {
void* arg = p_tasks->args[arg_index];
p_tasks->func(arg);
completed_count++;
} else {
break;
}
}
// sync point
atomic_fetch_add_explicit(&p_tasks->completed_count, completed_count, memory_order_release);
c11_thrdpool_debug_log(p_worker->index,
"Execution complete, waiting for `sync_val` reset...");
while(true) {
int sync_val = atomic_load_explicit(&p_tasks->sync_val, memory_order_relaxed);
if(sync_val == 0) break;
if(sync_val == -1) return 0; // force kill
c11_thrd__yield();
}
c11_thrdpool_debug_log(p_worker->index,
"`sync_val` reset detected, waiting for next tasks...");
}
return 0;
}
void c11_thrdpool__ctor(c11_thrdpool* pool, int length) {
pool->length = length;
atomic_store_explicit(&pool->ready_workers_num, 0, memory_order_relaxed);
pool->workers = PK_MALLOC(sizeof(c11_thrdpool_worker) * length);
c11_mutex__ctor(&pool->workers_mutex);
c11_cond__ctor(&pool->workers_cond);
atomic_store_explicit(&pool->tasks.sync_val, 0, memory_order_relaxed);
for(int i = 0; i < length; i++) {
c11_thrdpool_worker* p_worker = &pool->workers[i];
p_worker->index = i;
p_worker->p_ready_workers_num = &pool->ready_workers_num;
p_worker->p_mutex = &pool->workers_mutex;
p_worker->p_cond = &pool->workers_cond;
p_worker->p_tasks = &pool->tasks;
bool ok = c11_thrd__create(&p_worker->thread, _thrdpool_worker, p_worker);
c11__rtassert(ok);
}
}
void c11_thrdpool__dtor(c11_thrdpool* pool) {
c11_mutex__lock(&pool->workers_mutex);
atomic_store_explicit(&pool->tasks.sync_val, -1, memory_order_relaxed);
c11_thrdpool_debug_log(-1, "Terminating all workers...");
c11_cond__broadcast(&pool->workers_cond);
c11_mutex__unlock(&pool->workers_mutex);
for(int i = 0; i < pool->length; i++) {
c11_thrdpool_worker* p_worker = &pool->workers[i];
c11_thrd__join(p_worker->thread);
}
c11_mutex__dtor(&pool->workers_mutex);
c11_cond__dtor(&pool->workers_cond);
PK_FREE(pool->workers);
}
void c11_thrdpool__map(c11_thrdpool* pool, c11_thrdpool_func_t func, void** args, int num_tasks) {
c11_thrdpool_debug_log(-1, "c11_thrdpool__map() called on %d tasks...", num_tasks);
while(atomic_load_explicit(&pool->ready_workers_num, memory_order_relaxed) < pool->length) {
c11_thrd__yield();
}
c11_thrdpool_debug_log(-1, "All %d workers are ready.", pool->length);
// assign tasks
c11_mutex__lock(&pool->workers_mutex);
pool->tasks.func = func;
pool->tasks.args = args;
pool->tasks.length = num_tasks;
atomic_store_explicit(&pool->tasks.sync_val, 1, memory_order_relaxed);
atomic_store_explicit(&pool->tasks.current_index, 0, memory_order_relaxed);
atomic_store_explicit(&pool->tasks.completed_count, 0, memory_order_relaxed);
c11_cond__broadcast(&pool->workers_cond);
c11_mutex__unlock(&pool->workers_mutex);
}
void c11_thrdpool__join(c11_thrdpool *pool) {
// wait for complete
int num_tasks = pool->tasks.length;
c11_thrdpool_debug_log(-1, "Waiting for %d tasks to complete...", num_tasks);
while(atomic_load_explicit(&pool->tasks.completed_count, memory_order_acquire) < num_tasks) {
c11_thrd__yield();
}
atomic_store_explicit(&pool->tasks.sync_val, 0, memory_order_relaxed);
c11_thrdpool_debug_log(-1, "All %d tasks completed, `sync_val` was reset.", num_tasks);
}
#undef C11_THRDPOOL_DEBUG
#ifdef c11_thrdpool_debug_log
#undef c11_thrdpool_debug_log
#endif
#endif // PK_ENABLE_THREADS
// src/common\vector.c
#include <string.h>
void c11_vector__ctor(c11_vector* self, int elem_size) {
self->data = NULL;
self->length = 0;
self->capacity = 0;
self->elem_size = elem_size;
}
void c11_vector__dtor(c11_vector* self) {
if(self->data) PK_FREE(self->data);
self->data = NULL;
self->length = 0;
self->capacity = 0;
}
c11_vector c11_vector__copy(const c11_vector* self) {
c11_vector retval;
c11_vector__ctor(&retval, self->elem_size);
c11_vector__reserve(&retval, self->capacity);
memcpy(retval.data, self->data, (size_t)self->elem_size * (size_t)self->length);
retval.length = self->length;
return retval;
}
void c11_vector__reserve(c11_vector* self, int capacity) {
if(capacity < 4) capacity = 4;
if(capacity <= self->capacity) return;
// self->elem_size * capacity may overflow
self->data = PK_REALLOC(self->data, (size_t)self->elem_size * (size_t)capacity);
if(self->data == NULL) c11__abort("c11_vector__reserve(): out of memory");
self->capacity = capacity;
}
void c11_vector__clear(c11_vector* self) { self->length = 0; }
void* c11_vector__emplace(c11_vector* self) {
if(self->length == self->capacity) { c11_vector__reserve(self, c11_vector__nextcap(self)); }
void* p = (char*)self->data + (size_t)self->elem_size * (size_t)self->length;
self->length++;
return p;
}
bool c11_vector__contains(const c11_vector* self, void* elem) {
for(int i = 0; i < self->length; i++) {
void* p = (char*)self->data + (size_t)self->elem_size * (size_t)i;
if(memcmp(p, elem, self->elem_size) == 0) return true;
}
return false;
}
void* c11_vector__submit(c11_vector* self, int* length) {
void* retval = self->data;
*length = self->length;
self->data = NULL;
self->length = 0;
self->capacity = 0;
return retval;
}
void c11_vector__swap(c11_vector* self, c11_vector* other) {
c11_vector tmp = *self;
*self = *other;
*other = tmp;
}
int c11_vector__nextcap(c11_vector* self) {
if(self->capacity < 1024) {
return self->capacity * 2;
} else {
// increase by 25%
return self->capacity + (self->capacity >> 2);
}
}
void c11_vector__extend(c11_vector* self, const void* p, int size) {
if (size <= 0) return;
int min_capacity = self->length + size;
if(self->capacity < min_capacity) {
int nextcap = c11_vector__nextcap(self);
c11_vector__reserve((self), c11__max(nextcap, min_capacity));
}
void* dst = (char*)self->data + self->length * self->elem_size;
memcpy(dst, p, size * self->elem_size);
self->length += size;
}
// src/common\_generated.c
// generated by prebuild.py
#include <string.h>
const char kPythonLibs_bisect[] = "\"\"\"Bisection algorithms.\"\"\"\n\ndef insort_right(a, x, lo=0, hi=None):\n \"\"\"Insert item x in list a, and keep it sorted assuming a is sorted.\n\n If x is already in a, insert it to the right of the rightmost x.\n\n Optional args lo (default 0) and hi (default len(a)) bound the\n slice of a to be searched.\n \"\"\"\n\n lo = bisect_right(a, x, lo, hi)\n a.insert(lo, x)\n\ndef bisect_right(a, x, lo=0, hi=None):\n \"\"\"Return the index where to insert item x in list a, assuming a is sorted.\n\n The return value i is such that all e in a[:i] have e <= x, and all e in\n a[i:] have e > x. So if x already appears in the list, a.insert(x) will\n insert just after the rightmost x already there.\n\n Optional args lo (default 0) and hi (default len(a)) bound the\n slice of a to be searched.\n \"\"\"\n\n if lo < 0:\n raise ValueError('lo must be non-negative')\n if hi is None:\n hi = len(a)\n while lo < hi:\n mid = (lo+hi)//2\n if x < a[mid]: hi = mid\n else: lo = mid+1\n return lo\n\ndef insort_left(a, x, lo=0, hi=None):\n \"\"\"Insert item x in list a, and keep it sorted assuming a is sorted.\n\n If x is already in a, insert it to the left of the leftmost x.\n\n Optional args lo (default 0) and hi (default len(a)) bound the\n slice of a to be searched.\n \"\"\"\n\n lo = bisect_left(a, x, lo, hi)\n a.insert(lo, x)\n\n\ndef bisect_left(a, x, lo=0, hi=None):\n \"\"\"Return the index where to insert item x in list a, assuming a is sorted.\n\n The return value i is such that all e in a[:i] have e < x, and all e in\n a[i:] have e >= x. So if x already appears in the list, a.insert(x) will\n insert just before the leftmost x already there.\n\n Optional args lo (default 0) and hi (default len(a)) bound the\n slice of a to be searched.\n \"\"\"\n\n if lo < 0:\n raise ValueError('lo must be non-negative')\n if hi is None:\n hi = len(a)\n while lo < hi:\n mid = (lo+hi)//2\n if a[mid] < x: lo = mid+1\n else: hi = mid\n return lo\n\n# Create aliases\nbisect = bisect_right\ninsort = insort_right\n";
const char kPythonLibs_builtins[] = "def all(iterable):\n for i in iterable:\n if not i:\n return False\n return True\n\ndef any(iterable):\n for i in iterable:\n if i:\n return True\n return False\n\ndef enumerate(iterable, start=0):\n n = start\n for elem in iterable:\n yield n, elem\n n += 1\n\ndef __minmax_reduce(op, args):\n if len(args) == 2: # min(1, 2)\n return args[0] if op(args[0], args[1]) else args[1]\n if len(args) == 0: # min()\n raise TypeError('expected 1 arguments, got 0')\n if len(args) == 1: # min([1, 2, 3, 4]) -> min(1, 2, 3, 4)\n args = args[0]\n args = iter(args)\n try:\n res = next(args)\n except StopIteration:\n raise ValueError('args is an empty sequence')\n while True:\n try:\n i = next(args)\n except StopIteration:\n break\n if op(i, res):\n res = i\n return res\n\ndef min(*args, key=None):\n key = key or (lambda x: x)\n return __minmax_reduce(lambda x,y: key(x)<key(y), args)\n\ndef max(*args, key=None):\n key = key or (lambda x: x)\n return __minmax_reduce(lambda x,y: key(x)>key(y), args)\n\ndef sum(iterable):\n res = 0\n for i in iterable:\n res += i\n return res\n\ndef map(f, iterable):\n for i in iterable:\n yield f(i)\n\ndef filter(f, iterable):\n for i in iterable:\n if f(i):\n yield i\n\nclass zip:\n def __init__(self, *iterables):\n self.iterables = [iter(it) for it in iterables]\n\n def __iter__(self):\n return self\n\n def __next__(self):\n result = []\n for it in self.iterables:\n result.append(next(it))\n return tuple(result)\n\ndef reversed(iterable):\n a = list(iterable)\n a.reverse()\n return a\n\ndef sorted(iterable, key=None, reverse=False):\n a = list(iterable)\n a.sort(key=key, reverse=reverse)\n return a\n\n\ndef help(obj):\n if hasattr(obj, '__func__'):\n obj = obj.__func__\n # print(obj.__signature__)\n if obj.__doc__:\n print(obj.__doc__)\n\ndef complex(real, imag=0):\n import cmath\n return cmath.complex(real, imag) # type: ignore\n\ndef dir(obj) -> list[str]:\n tp_module = type(__import__('math'))\n if isinstance(obj, tp_module):\n return [k for k, _ in obj.__dict__.items()]\n names = set()\n if not isinstance(obj, type):\n obj_d = obj.__dict__\n if obj_d is not None:\n names.update([k for k, _ in obj_d.items()])\n cls = type(obj)\n else:\n cls = obj\n while cls is not None:\n names.update([k for k, _ in cls.__dict__.items()])\n cls = cls.__base__\n return sorted(list(names))\n\nclass set:\n def __init__(self, iterable=None):\n iterable = iterable or []\n self._a = {}\n self.update(iterable)\n\n def add(self, elem):\n self._a[elem] = None\n \n def discard(self, elem):\n self._a.pop(elem, None)\n\n def remove(self, elem):\n del self._a[elem]\n \n def clear(self):\n self._a.clear()\n\n def update(self, other):\n for elem in other:\n self.add(elem)\n\n def __len__(self):\n return len(self._a)\n \n def copy(self):\n return set(self._a.keys())\n \n def __and__(self, other):\n return {elem for elem in self if elem in other}\n\n def __sub__(self, other):\n return {elem for elem in self if elem not in other}\n \n def __or__(self, other):\n ret = self.copy()\n ret.update(other)\n return ret\n\n def __xor__(self, other): \n _0 = self - other\n _1 = other - self\n return _0 | _1\n\n def union(self, other):\n return self | other\n\n def intersection(self, other):\n return self & other\n\n def difference(self, other):\n return self - other\n\n def symmetric_difference(self, other): \n return self ^ other\n \n def __eq__(self, other):\n if not isinstance(other, set):\n return NotImplemented\n return len(self ^ other) == 0\n \n def __ne__(self, other):\n if not isinstance(other, set):\n return NotImplemented\n return len(self ^ other) != 0\n\n def isdisjoint(self, other):\n return len(self & other) == 0\n \n def issubset(self, other):\n return len(self - other) == 0\n \n def issuperset(self, other):\n return len(other - self) == 0\n\n def __contains__(self, elem):\n return elem in self._a\n \n def __repr__(self):\n if len(self) == 0:\n return 'set()'\n return '{'+ ', '.join([repr(i) for i in self._a.keys()]) + '}'\n \n def __iter__(self):\n return iter(self._a.keys())";
const char kPythonLibs_cmath[] = "import math\n\nclass complex:\n def __init__(self, real, imag=0):\n self._real = float(real)\n self._imag = float(imag)\n\n @property\n def real(self):\n return self._real\n \n @property\n def imag(self):\n return self._imag\n\n def conjugate(self):\n return complex(self.real, -self.imag)\n \n def __repr__(self):\n s = ['(', str(self.real)]\n s.append('-' if self.imag < 0 else '+')\n s.append(str(abs(self.imag)))\n s.append('j)')\n return ''.join(s)\n \n def __eq__(self, other):\n if type(other) is complex:\n return self.real == other.real and self.imag == other.imag\n if type(other) in (int, float):\n return self.real == other and self.imag == 0\n return NotImplemented\n \n def __ne__(self, other):\n res = self == other\n if res is NotImplemented:\n return res\n return not res\n \n def __add__(self, other):\n if type(other) is complex:\n return complex(self.real + other.real, self.imag + other.imag)\n if type(other) in (int, float):\n return complex(self.real + other, self.imag)\n return NotImplemented\n \n def __radd__(self, other):\n return self.__add__(other)\n \n def __sub__(self, other):\n if type(other) is complex:\n return complex(self.real - other.real, self.imag - other.imag)\n if type(other) in (int, float):\n return complex(self.real - other, self.imag)\n return NotImplemented\n \n def __rsub__(self, other):\n if type(other) is complex:\n return complex(other.real - self.real, other.imag - self.imag)\n if type(other) in (int, float):\n return complex(other - self.real, -self.imag)\n return NotImplemented\n \n def __mul__(self, other):\n if type(other) is complex:\n return complex(self.real * other.real - self.imag * other.imag,\n self.real * other.imag + self.imag * other.real)\n if type(other) in (int, float):\n return complex(self.real * other, self.imag * other)\n return NotImplemented\n \n def __rmul__(self, other):\n return self.__mul__(other)\n \n def __truediv__(self, other):\n if type(other) is complex:\n denominator = other.real ** 2 + other.imag ** 2\n real_part = (self.real * other.real + self.imag * other.imag) / denominator\n imag_part = (self.imag * other.real - self.real * other.imag) / denominator\n return complex(real_part, imag_part)\n if type(other) in (int, float):\n return complex(self.real / other, self.imag / other)\n return NotImplemented\n \n def __pow__(self, other: int | float):\n if type(other) in (int, float):\n return complex(self.__abs__() ** other * math.cos(other * phase(self)),\n self.__abs__() ** other * math.sin(other * phase(self)))\n return NotImplemented\n \n def __abs__(self) -> float:\n return math.sqrt(self.real ** 2 + self.imag ** 2)\n\n def __neg__(self):\n return complex(-self.real, -self.imag)\n \n def __hash__(self):\n return hash((self.real, self.imag))\n\n\n# Conversions to and from polar coordinates\n\ndef phase(z: complex):\n return math.atan2(z.imag, z.real)\n\ndef polar(z: complex):\n return z.__abs__(), phase(z)\n\ndef rect(r: float, phi: float):\n return r * math.cos(phi) + r * math.sin(phi) * 1j\n\n# Power and logarithmic functions\n\ndef exp(z: complex):\n return math.exp(z.real) * rect(1, z.imag)\n\ndef log(z: complex, base=2.718281828459045):\n return math.log(z.__abs__(), base) + phase(z) * 1j\n\ndef log10(z: complex):\n return log(z, 10)\n\ndef sqrt(z: complex):\n return z ** 0.5\n\n# Trigonometric functions\n\ndef acos(z: complex):\n return -1j * log(z + sqrt(z * z - 1))\n\ndef asin(z: complex):\n return -1j * log(1j * z + sqrt(1 - z * z))\n\ndef atan(z: complex):\n return 1j / 2 * log((1 - 1j * z) / (1 + 1j * z))\n\ndef cos(z: complex):\n return (exp(1j * z) + exp(-1j * z)) / 2\n\ndef sin(z: complex):\n return (exp(1j * z) - exp(-1j * z)) / (2 * 1j)\n\ndef tan(z: complex):\n return sin(z) / cos(z)\n\n# Hyperbolic functions\n\ndef acosh(z: complex):\n return log(z + sqrt(z * z - 1))\n\ndef asinh(z: complex):\n return log(z + sqrt(z * z + 1))\n\ndef atanh(z: complex):\n return 1 / 2 * log((1 + z) / (1 - z))\n\ndef cosh(z: complex):\n return (exp(z) + exp(-z)) / 2\n\ndef sinh(z: complex):\n return (exp(z) - exp(-z)) / 2\n\ndef tanh(z: complex):\n return sinh(z) / cosh(z)\n\n# Classification functions\n\ndef isfinite(z: complex):\n return math.isfinite(z.real) and math.isfinite(z.imag)\n\ndef isinf(z: complex):\n return math.isinf(z.real) or math.isinf(z.imag)\n\ndef isnan(z: complex):\n return math.isnan(z.real) or math.isnan(z.imag)\n\ndef isclose(a: complex, b: complex):\n return math.isclose(a.real, b.real) and math.isclose(a.imag, b.imag)\n\n# Constants\n\npi = math.pi\ne = math.e\ntau = 2 * pi\ninf = math.inf\ninfj = complex(0, inf)\nnan = math.nan\nnanj = complex(0, nan)\n";
const char kPythonLibs_collections[] = "from typing import TypeVar, Iterable\n\ndef Counter[T](iterable: Iterable[T]):\n a: dict[T, int] = {}\n for x in iterable:\n if x in a:\n a[x] += 1\n else:\n a[x] = 1\n return a\n\n\nclass defaultdict(dict):\n def __init__(self, default_factory, *args):\n super().__init__(*args)\n self.default_factory = default_factory\n\n def __missing__(self, key):\n self[key] = self.default_factory()\n return self[key]\n\n def __repr__(self) -> str:\n return f\"defaultdict({self.default_factory}, {super().__repr__()})\"\n\n def copy(self):\n return defaultdict(self.default_factory, self)\n\n\nclass deque[T]:\n _head: int\n _tail: int\n _maxlen: int | None\n _capacity: int\n _data: list[T]\n\n def __init__(self, iterable: Iterable[T] = None, maxlen: int | None = None):\n if maxlen is not None:\n assert maxlen > 0\n\n self._head = 0\n self._tail = 0\n self._maxlen = maxlen\n self._capacity = 8 if maxlen is None else maxlen + 1\n self._data = [None] * self._capacity # type: ignore\n\n if iterable is not None:\n self.extend(iterable)\n\n @property\n def maxlen(self) -> int | None:\n return self._maxlen\n\n def __resize_2x(self):\n backup = list(self)\n self._capacity *= 2\n self._head = 0\n self._tail = len(backup)\n self._data.clear()\n self._data.extend(backup)\n self._data.extend([None] * (self._capacity - len(backup)))\n\n def append(self, x: T):\n if (self._tail + 1) % self._capacity == self._head:\n if self._maxlen is None:\n self.__resize_2x()\n else:\n self.popleft()\n self._data[self._tail] = x\n self._tail = (self._tail + 1) % self._capacity\n\n def appendleft(self, x: T):\n if (self._tail + 1) % self._capacity == self._head:\n if self._maxlen is None:\n self.__resize_2x()\n else:\n self.pop()\n self._head = (self._head - 1) % self._capacity\n self._data[self._head] = x\n\n def copy(self):\n return deque(self, maxlen=self.maxlen)\n \n def count(self, x: T) -> int:\n n = 0\n for item in self:\n if item == x:\n n += 1\n return n\n \n def extend(self, iterable: Iterable[T]):\n for x in iterable:\n self.append(x)\n\n def extendleft(self, iterable: Iterable[T]):\n for x in iterable:\n self.appendleft(x)\n \n def pop(self) -> T:\n if self._head == self._tail:\n raise IndexError(\"pop from an empty deque\")\n self._tail = (self._tail - 1) % self._capacity\n x = self._data[self._tail]\n self._data[self._tail] = None\n return x\n \n def popleft(self) -> T:\n if self._head == self._tail:\n raise IndexError(\"pop from an empty deque\")\n x = self._data[self._head]\n self._data[self._head] = None\n self._head = (self._head + 1) % self._capacity\n return x\n \n def clear(self):\n i = self._head\n while i != self._tail:\n self._data[i] = None # type: ignore\n i = (i + 1) % self._capacity\n self._head = 0\n self._tail = 0\n\n def rotate(self, n: int = 1):\n if len(self) == 0:\n return\n if n > 0:\n n = n % len(self)\n for _ in range(n):\n self.appendleft(self.pop())\n elif n < 0:\n n = -n % len(self)\n for _ in range(n):\n self.append(self.popleft())\n\n def __len__(self) -> int:\n return (self._tail - self._head) % self._capacity\n\n def __contains__(self, x: object) -> bool:\n for item in self:\n if item == x:\n return True\n return False\n \n def __iter__(self):\n i = self._head\n while i != self._tail:\n yield self._data[i]\n i = (i + 1) % self._capacity\n\n def __eq__(self, other: object) -> bool:\n if not isinstance(other, deque):\n return NotImplemented\n if len(self) != len(other):\n return False\n for x, y in zip(self, other):\n if x != y:\n return False\n return True\n \n def __ne__(self, other: object) -> bool:\n if not isinstance(other, deque):\n return NotImplemented\n return not self == other\n \n def __repr__(self) -> str:\n if self.maxlen is None:\n return f\"deque({list(self)!r})\"\n return f\"deque({list(self)!r}, maxlen={self.maxlen})\"\n\n";
const char kPythonLibs_dataclasses[] = "def _get_annotations(cls: type):\n inherits = []\n while cls is not object:\n inherits.append(cls)\n cls = cls.__base__\n inherits.reverse()\n res = {}\n for cls in inherits:\n res.update(cls.__annotations__)\n return res.keys()\n\ndef _wrapped__init__(self, *args, **kwargs):\n cls = type(self)\n cls_d = cls.__dict__\n fields = _get_annotations(cls)\n i = 0 # index into args\n for field in fields:\n if field in kwargs:\n setattr(self, field, kwargs.pop(field))\n else:\n if i < len(args):\n setattr(self, field, args[i])\n i += 1\n elif field in cls_d: # has default value\n setattr(self, field, cls_d[field])\n else:\n raise TypeError(f\"{cls.__name__} missing required argument {field!r}\")\n if len(args) > i:\n raise TypeError(f\"{cls.__name__} takes {len(fields)} positional arguments but {len(args)} were given\")\n if len(kwargs) > 0:\n raise TypeError(f\"{cls.__name__} got an unexpected keyword argument {next(iter(kwargs))!r}\")\n\ndef _wrapped__repr__(self):\n fields = _get_annotations(type(self))\n obj_d = self.__dict__\n args: list = [f\"{field}={obj_d[field]!r}\" for field in fields]\n return f\"{type(self).__name__}({', '.join(args)})\"\n\ndef _wrapped__eq__(self, other):\n if type(self) is not type(other):\n return False\n fields = _get_annotations(type(self))\n for field in fields:\n if getattr(self, field) != getattr(other, field):\n return False\n return True\n\ndef _wrapped__ne__(self, other):\n return not self.__eq__(other)\n\ndef dataclass(cls: type):\n assert type(cls) is type\n cls_d = cls.__dict__\n if '__init__' not in cls_d:\n cls.__init__ = _wrapped__init__\n if '__repr__' not in cls_d:\n cls.__repr__ = _wrapped__repr__\n if '__eq__' not in cls_d:\n cls.__eq__ = _wrapped__eq__\n if '__ne__' not in cls_d:\n cls.__ne__ = _wrapped__ne__\n fields = _get_annotations(cls)\n has_default = False\n for field in fields:\n if field in cls_d:\n has_default = True\n else:\n if has_default:\n raise TypeError(f\"non-default argument {field!r} follows default argument\")\n return cls\n\ndef asdict(obj) -> dict:\n fields = _get_annotations(type(obj))\n obj_d = obj.__dict__\n return {field: obj_d[field] for field in fields}";
const char kPythonLibs_datetime[] = "from time import localtime\nimport operator\n\nclass timedelta:\n def __init__(self, days=0, seconds=0):\n self.days = days\n self.seconds = seconds\n\n def __repr__(self):\n return f\"datetime.timedelta(days={self.days}, seconds={self.seconds})\"\n\n def __eq__(self, other) -> bool:\n if not isinstance(other, timedelta):\n return NotImplemented\n return (self.days, self.seconds) == (other.days, other.seconds)\n\n def __ne__(self, other) -> bool:\n if not isinstance(other, timedelta):\n return NotImplemented\n return (self.days, self.seconds) != (other.days, other.seconds)\n\n\nclass date:\n def __init__(self, year: int, month: int, day: int):\n self.year = year\n self.month = month\n self.day = day\n\n @staticmethod\n def today():\n t = localtime()\n return date(t.tm_year, t.tm_mon, t.tm_mday)\n \n def __cmp(self, other, op):\n if not isinstance(other, date):\n return NotImplemented\n if self.year != other.year:\n return op(self.year, other.year)\n if self.month != other.month:\n return op(self.month, other.month)\n return op(self.day, other.day)\n\n def __eq__(self, other) -> bool:\n return self.__cmp(other, operator.eq)\n \n def __ne__(self, other) -> bool:\n return self.__cmp(other, operator.ne)\n\n def __lt__(self, other: 'date') -> bool:\n return self.__cmp(other, operator.lt)\n\n def __le__(self, other: 'date') -> bool:\n return self.__cmp(other, operator.le)\n\n def __gt__(self, other: 'date') -> bool:\n return self.__cmp(other, operator.gt)\n\n def __ge__(self, other: 'date') -> bool:\n return self.__cmp(other, operator.ge)\n\n def __str__(self):\n return f\"{self.year}-{self.month:02}-{self.day:02}\"\n\n def __repr__(self):\n return f\"datetime.date({self.year}, {self.month}, {self.day})\"\n\n\nclass datetime(date):\n def __init__(self, year: int, month: int, day: int, hour: int, minute: int, second: int):\n super().__init__(year, month, day)\n # Validate and set hour, minute, and second\n if not 0 <= hour <= 23:\n raise ValueError(\"Hour must be between 0 and 23\")\n self.hour = hour\n if not 0 <= minute <= 59:\n raise ValueError(\"Minute must be between 0 and 59\")\n self.minute = minute\n if not 0 <= second <= 59:\n raise ValueError(\"Second must be between 0 and 59\")\n self.second = second\n\n def date(self) -> date:\n return date(self.year, self.month, self.day)\n\n @staticmethod\n def now():\n t = localtime()\n tm_sec = t.tm_sec\n if tm_sec == 60:\n tm_sec = 59\n return datetime(t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, tm_sec)\n\n def __str__(self):\n return f\"{self.year}-{self.month:02}-{self.day:02} {self.hour:02}:{self.minute:02}:{self.second:02}\"\n\n def __repr__(self):\n return f\"datetime.datetime({self.year}, {self.month}, {self.day}, {self.hour}, {self.minute}, {self.second})\"\n\n def __cmp(self, other, op):\n if not isinstance(other, datetime):\n return NotImplemented\n if self.year != other.year:\n return op(self.year, other.year)\n if self.month != other.month:\n return op(self.month, other.month)\n if self.day != other.day:\n return op(self.day, other.day)\n if self.hour != other.hour:\n return op(self.hour, other.hour)\n if self.minute != other.minute:\n return op(self.minute, other.minute)\n return op(self.second, other.second)\n\n def __eq__(self, other) -> bool:\n return self.__cmp(other, operator.eq)\n \n def __ne__(self, other) -> bool:\n return self.__cmp(other, operator.ne)\n \n def __lt__(self, other) -> bool:\n return self.__cmp(other, operator.lt)\n \n def __le__(self, other) -> bool:\n return self.__cmp(other, operator.le)\n \n def __gt__(self, other) -> bool:\n return self.__cmp(other, operator.gt)\n \n def __ge__(self, other) -> bool:\n return self.__cmp(other, operator.ge)\n\n\n";
const char kPythonLibs_functools[] = "class cache:\n def __init__(self, f):\n self.f = f\n self.cache = {}\n\n def __call__(self, *args):\n if args not in self.cache:\n self.cache[args] = self.f(*args)\n return self.cache[args]\n \nclass lru_cache:\n def __init__(self, maxsize=128):\n self.maxsize = maxsize\n self.cache = {}\n\n def __call__(self, f):\n def wrapped(*args):\n if args in self.cache:\n res = self.cache.pop(args)\n self.cache[args] = res\n return res\n \n res = f(*args)\n if len(self.cache) >= self.maxsize:\n first_key = next(iter(self.cache))\n self.cache.pop(first_key)\n self.cache[args] = res\n return res\n return wrapped\n \ndef reduce(function, sequence, initial=...):\n it = iter(sequence)\n if initial is ...:\n try:\n value = next(it)\n except StopIteration:\n raise TypeError(\"reduce() of empty sequence with no initial value\")\n else:\n value = initial\n for element in it:\n value = function(value, element)\n return value\n\nclass partial:\n def __init__(self, f, *args, **kwargs):\n self.f = f\n if not callable(f):\n raise TypeError(\"the first argument must be callable\")\n self.args = args\n self.kwargs = kwargs\n\n def __call__(self, *args, **kwargs):\n kwargs.update(self.kwargs)\n return self.f(*self.args, *args, **kwargs)\n\n";
const char kPythonLibs_heapq[] = "# Heap queue algorithm (a.k.a. priority queue)\ndef heappush(heap, item):\n \"\"\"Push item onto heap, maintaining the heap invariant.\"\"\"\n heap.append(item)\n _siftdown(heap, 0, len(heap)-1)\n\ndef heappop(heap):\n \"\"\"Pop the smallest item off the heap, maintaining the heap invariant.\"\"\"\n lastelt = heap.pop() # raises appropriate IndexError if heap is empty\n if heap:\n returnitem = heap[0]\n heap[0] = lastelt\n _siftup(heap, 0)\n return returnitem\n return lastelt\n\ndef heapreplace(heap, item):\n \"\"\"Pop and return the current smallest value, and add the new item.\n\n This is more efficient than heappop() followed by heappush(), and can be\n more appropriate when using a fixed-size heap. Note that the value\n returned may be larger than item! That constrains reasonable uses of\n this routine unless written as part of a conditional replacement:\n\n if item > heap[0]:\n item = heapreplace(heap, item)\n \"\"\"\n returnitem = heap[0] # raises appropriate IndexError if heap is empty\n heap[0] = item\n _siftup(heap, 0)\n return returnitem\n\ndef heappushpop(heap, item):\n \"\"\"Fast version of a heappush followed by a heappop.\"\"\"\n if heap and heap[0] < item:\n item, heap[0] = heap[0], item\n _siftup(heap, 0)\n return item\n\ndef heapify(x):\n \"\"\"Transform list into a heap, in-place, in O(len(x)) time.\"\"\"\n n = len(x)\n # Transform bottom-up. The largest index there's any point to looking at\n # is the largest with a child index in-range, so must have 2*i + 1 < n,\n # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so\n # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is\n # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.\n for i in reversed(range(n//2)):\n _siftup(x, i)\n\n# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos\n# is the index of a leaf with a possibly out-of-order value. Restore the\n# heap invariant.\ndef _siftdown(heap, startpos, pos):\n newitem = heap[pos]\n # Follow the path to the root, moving parents down until finding a place\n # newitem fits.\n while pos > startpos:\n parentpos = (pos - 1) >> 1\n parent = heap[parentpos]\n if newitem < parent:\n heap[pos] = parent\n pos = parentpos\n continue\n break\n heap[pos] = newitem\n\ndef _siftup(heap, pos):\n endpos = len(heap)\n startpos = pos\n newitem = heap[pos]\n # Bubble up the smaller child until hitting a leaf.\n childpos = 2*pos + 1 # leftmost child position\n while childpos < endpos:\n # Set childpos to index of smaller child.\n rightpos = childpos + 1\n if rightpos < endpos and not heap[childpos] < heap[rightpos]:\n childpos = rightpos\n # Move the smaller child up.\n heap[pos] = heap[childpos]\n pos = childpos\n childpos = 2*pos + 1\n # The leaf at pos is empty now. Put newitem there, and bubble it up\n # to its final resting place (by sifting its parents down).\n heap[pos] = newitem\n _siftdown(heap, startpos, pos)";
const char kPythonLibs_linalg[] = "from vmath import *";
const char kPythonLibs_operator[] = "# https://docs.python.org/3/library/operator.html#mapping-operators-to-functions\n\ndef le(a, b): return a <= b\ndef lt(a, b): return a < b\ndef ge(a, b): return a >= b\ndef gt(a, b): return a > b\ndef eq(a, b): return a == b\ndef ne(a, b): return a != b\n\ndef and_(a, b): return a & b\ndef or_(a, b): return a | b\ndef xor(a, b): return a ^ b\ndef invert(a): return ~a\ndef lshift(a, b): return a << b\ndef rshift(a, b): return a >> b\n\ndef is_(a, b): return a is b\ndef is_not(a, b): return a is not b\ndef not_(a): return not a\ndef truth(a): return bool(a)\ndef contains(a, b): return b in a\n\ndef add(a, b): return a + b\ndef sub(a, b): return a - b\ndef mul(a, b): return a * b\ndef truediv(a, b): return a / b\ndef floordiv(a, b): return a // b\ndef mod(a, b): return a % b\ndef pow(a, b): return a ** b\ndef neg(a): return -a\ndef matmul(a, b): return a @ b\n\ndef getitem(a, b): return a[b]\ndef setitem(a, b, c): a[b] = c\ndef delitem(a, b): del a[b]\n\ndef iadd(a, b): a += b; return a\ndef isub(a, b): a -= b; return a\ndef imul(a, b): a *= b; return a\ndef itruediv(a, b): a /= b; return a\ndef ifloordiv(a, b): a //= b; return a\ndef imod(a, b): a %= b; return a\n# def ipow(a, b): a **= b; return a\n# def imatmul(a, b): a @= b; return a\ndef iand(a, b): a &= b; return a\ndef ior(a, b): a |= b; return a\ndef ixor(a, b): a ^= b; return a\ndef ilshift(a, b): a <<= b; return a\ndef irshift(a, b): a >>= b; return a\n\nclass attrgetter:\n def __init__(self, attr):\n self.attr = attr\n def __call__(self, obj):\n return getattr(obj, self.attr)\n";
const char kPythonLibs_typing[] = "class _Placeholder:\n def __init__(self, *args, **kwargs):\n pass\n def __getitem__(self, *args):\n return self\n def __call__(self, *args, **kwargs):\n return self\n def __and__(self, other):\n return self\n def __or__(self, other):\n return self\n def __xor__(self, other):\n return self\n\n\n_PLACEHOLDER = _Placeholder()\n\nSequence = _PLACEHOLDER\nList = _PLACEHOLDER\nDict = _PLACEHOLDER\nTuple = _PLACEHOLDER\nSet = _PLACEHOLDER\nAny = _PLACEHOLDER\nUnion = _PLACEHOLDER\nOptional = _PLACEHOLDER\nCallable = _PLACEHOLDER\nType = _PLACEHOLDER\nTypeAlias = _PLACEHOLDER\nNewType = _PLACEHOLDER\n\nClassVar = _PLACEHOLDER\n\nLiteral = _PLACEHOLDER\nLiteralString = _PLACEHOLDER\n\nIterable = _PLACEHOLDER\nGenerator = _PLACEHOLDER\nIterator = _PLACEHOLDER\n\nHashable = _PLACEHOLDER\n\nTypeVar = _PLACEHOLDER\nSelf = _PLACEHOLDER\n\nProtocol = object\nGeneric = object\nNever = object\n\nTYPE_CHECKING = False\n\n# decorators\noverload = lambda x: x\nfinal = lambda x: x\n\n# exhaustiveness checking\nassert_never = lambda x: x\n\nTypedDict = dict\nNotRequired = _PLACEHOLDER\n\ncast = lambda _, val: val\n";
const char* load_kPythonLib(const char* name) {
if (strchr(name, '.') != NULL) return NULL;
if (strcmp(name, "bisect") == 0) return kPythonLibs_bisect;
if (strcmp(name, "builtins") == 0) return kPythonLibs_builtins;
if (strcmp(name, "cmath") == 0) return kPythonLibs_cmath;
if (strcmp(name, "collections") == 0) return kPythonLibs_collections;
if (strcmp(name, "dataclasses") == 0) return kPythonLibs_dataclasses;
if (strcmp(name, "datetime") == 0) return kPythonLibs_datetime;
if (strcmp(name, "functools") == 0) return kPythonLibs_functools;
if (strcmp(name, "heapq") == 0) return kPythonLibs_heapq;
if (strcmp(name, "linalg") == 0) return kPythonLibs_linalg;
if (strcmp(name, "operator") == 0) return kPythonLibs_operator;
if (strcmp(name, "typing") == 0) return kPythonLibs_typing;
return NULL;
}
// src/compiler\compiler.c
#include <assert.h>
#include <stdbool.h>
/* expr.h */
typedef struct Expr Expr;
typedef struct Ctx Ctx;
typedef struct ExprVt {
/* emit */
void (*emit_)(Expr*, Ctx*);
bool (*emit_del)(Expr*, Ctx*);
bool (*emit_store)(Expr*, Ctx*);
void (*emit_inplace)(Expr*, Ctx*);
bool (*emit_istore)(Expr*, Ctx*);
/* reflections */
bool is_literal;
bool is_name; // NameExpr
bool is_tuple; // TupleExpr
bool is_attrib; // AttribExpr
bool is_subscr; // SubscrExpr
bool is_starred; // StarredExpr
bool is_binary; // BinaryExpr
bool is_ternary; // TernaryExpr
void (*dtor)(Expr*);
} ExprVt;
#define vtcall(f, self, ctx) ((self)->vt->f((self), (ctx)))
#define vtemit_(self, ctx) vtcall(emit_, (self), (ctx))
#define vtemit_del(self, ctx) ((self)->vt->emit_del ? vtcall(emit_del, self, ctx) : false)
#define vtemit_store(self, ctx) ((self)->vt->emit_store ? vtcall(emit_store, self, ctx) : false)
#define vtemit_inplace(self, ctx) \
((self)->vt->emit_inplace ? vtcall(emit_inplace, self, ctx) : vtemit_(self, ctx))
#define vtemit_istore(self, ctx) \
((self)->vt->emit_istore ? vtcall(emit_istore, self, ctx) : vtemit_store(self, ctx))
#define vtdelete(self) \
do { \
if(self) { \
if((self)->vt->dtor) (self)->vt->dtor(self); \
PK_FREE(self); \
} \
} while(0)
#define EXPR_COMMON_HEADER \
const ExprVt* vt; \
int line;
typedef struct Expr {
EXPR_COMMON_HEADER
} Expr;
/* context.h */
typedef struct Ctx {
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
FuncDecl* func; // optional, weakref
int level;
int curr_iblock;
bool is_compiling_class;
c11_vector /*T=Expr_p*/ s_expr;
c11_smallmap_n2d global_names;
c11_smallmap_v2d co_consts_string_dedup_map; // this stores 0-based index instead of pointer
} Ctx;
typedef struct Expr Expr;
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level);
static void Ctx__dtor(Ctx* self);
static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break);
static int Ctx__enter_block(Ctx* self, CodeBlockType type);
static void Ctx__exit_block(Ctx* self);
static int Ctx__emit_(Ctx* self, Opcode opcode, uint16_t arg, int line);
static int Ctx__emit_int(Ctx* self, int64_t value, int line);
static int Ctx__emit_name(Ctx* self, py_Name name, int line);
static void Ctx__patch_jump(Ctx* self, int index);
static void Ctx__emit_jump(Ctx* self, int target, int line);
static int Ctx__add_varname(Ctx* self, py_Name name);
static int Ctx__add_name(Ctx* self, py_Name name);
static int Ctx__add_const(Ctx* self, py_Ref);
static int Ctx__add_const_string(Ctx* self, c11_sv);
static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int line);
static void Ctx__s_emit_top(Ctx*); // emit top -> pop -> delete
static void Ctx__s_push(Ctx*, Expr*); // push
static Expr* Ctx__s_top(Ctx*); // top
static int Ctx__s_size(Ctx*); // size
static void Ctx__s_pop(Ctx*); // pop -> delete
static Expr* Ctx__s_popx(Ctx*); // pop move
static void Ctx__s_emit_decorators(Ctx*, int count);
/* expr.c */
typedef struct NameExpr {
EXPR_COMMON_HEADER
py_Name name;
NameScope scope;
} NameExpr;
void NameExpr__emit_(Expr* self_, Ctx* ctx) {
NameExpr* self = (NameExpr*)self_;
int index = c11_smallmap_n2d__get(&ctx->co->varnames_inv, self->name, -1);
if(self->scope == NAME_LOCAL && index >= 0) {
// we know this is a local variable
Ctx__emit_(ctx, OP_LOAD_FAST, index, self->line);
} else {
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
if(self->scope == NAME_GLOBAL) {
if(ctx->co->src->is_dynamic) {
op = OP_LOAD_NAME;
} else {
if(ctx->is_compiling_class) {
// if we are compiling a class, we should use `OP_LOAD_CLASS_GLOBAL`
// this is for @property.setter
op = OP_LOAD_CLASS_GLOBAL;
}
}
}
Ctx__emit_(ctx, op, Ctx__add_name(ctx, self->name), self->line);
}
}
bool NameExpr__emit_del(Expr* self_, Ctx* ctx) {
NameExpr* self = (NameExpr*)self_;
switch(self->scope) {
case NAME_LOCAL:
Ctx__emit_(ctx, OP_DELETE_FAST, Ctx__add_varname(ctx, self->name), self->line);
break;
case NAME_GLOBAL: {
Opcode op = ctx->co->src->is_dynamic ? OP_DELETE_NAME : OP_DELETE_GLOBAL;
Ctx__emit_(ctx, op, Ctx__add_name(ctx, self->name), self->line);
break;
}
default: c11__unreachable();
}
return true;
}
bool NameExpr__emit_store(Expr* self_, Ctx* ctx) {
NameExpr* self = (NameExpr*)self_;
if(ctx->is_compiling_class) {
Ctx__emit_(ctx, OP_STORE_CLASS_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true;
}
Ctx__emit_store_name(ctx, self->scope, self->name, self->line);
return true;
}
NameExpr* NameExpr__new(int line, py_Name name, NameScope scope) {
const static ExprVt Vt = {.emit_ = NameExpr__emit_,
.emit_del = NameExpr__emit_del,
.emit_store = NameExpr__emit_store,
.is_name = true};
NameExpr* self = PK_MALLOC(sizeof(NameExpr));
self->vt = &Vt;
self->line = line;
self->name = name;
self->scope = scope;
return self;
}
typedef struct StarredExpr {
EXPR_COMMON_HEADER
Expr* child;
int level;
} StarredExpr;
void StarredExpr__emit_(Expr* self_, Ctx* ctx) {
StarredExpr* self = (StarredExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_UNARY_STAR, self->level, self->line);
}
bool StarredExpr__emit_store(Expr* self_, Ctx* ctx) {
StarredExpr* self = (StarredExpr*)self_;
if(self->level != 1) return false;
// simply proxy to child
return vtemit_store(self->child, ctx);
}
void StarredExpr__dtor(Expr* self_) {
StarredExpr* self = (StarredExpr*)self_;
vtdelete(self->child);
}
StarredExpr* StarredExpr__new(int line, Expr* child, int level) {
const static ExprVt Vt = {.emit_ = StarredExpr__emit_,
.emit_store = StarredExpr__emit_store,
.is_starred = true,
.dtor = StarredExpr__dtor};
StarredExpr* self = PK_MALLOC(sizeof(StarredExpr));
self->vt = &Vt;
self->line = line;
self->child = child;
self->level = level;
return self;
}
// InvertExpr, NotExpr, NegatedExpr
// NOTE: NegatedExpr always contains a non-const child. Should not generate -1 or -0.1
typedef struct UnaryExpr {
EXPR_COMMON_HEADER
Expr* child;
Opcode opcode;
} UnaryExpr;
void UnaryExpr__dtor(Expr* self_) {
UnaryExpr* self = (UnaryExpr*)self_;
vtdelete(self->child);
}
static void UnaryExpr__emit_(Expr* self_, Ctx* ctx) {
UnaryExpr* self = (UnaryExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, self->opcode, BC_NOARG, self->line);
}
UnaryExpr* UnaryExpr__new(int line, Expr* child, Opcode opcode) {
const static ExprVt Vt = {.emit_ = UnaryExpr__emit_, .dtor = UnaryExpr__dtor};
UnaryExpr* self = PK_MALLOC(sizeof(UnaryExpr));
self->vt = &Vt;
self->line = line;
self->child = child;
self->opcode = opcode;
return self;
}
typedef struct FStringSpecExpr {
EXPR_COMMON_HEADER
Expr* child;
c11_sv spec;
} FStringSpecExpr;
void FStringSpecExpr__emit_(Expr* self_, Ctx* ctx) {
FStringSpecExpr* self = (FStringSpecExpr*)self_;
vtemit_(self->child, ctx);
int index = Ctx__add_const_string(ctx, self->spec);
Ctx__emit_(ctx, OP_FORMAT_STRING, index, self->line);
}
FStringSpecExpr* FStringSpecExpr__new(int line, Expr* child, c11_sv spec) {
const static ExprVt Vt = {.emit_ = FStringSpecExpr__emit_, .dtor = UnaryExpr__dtor};
FStringSpecExpr* self = PK_MALLOC(sizeof(FStringSpecExpr));
self->vt = &Vt;
self->line = line;
self->child = child;
self->spec = spec;
return self;
}
typedef struct RawStringExpr {
EXPR_COMMON_HEADER
c11_sv value;
Opcode opcode;
} RawStringExpr;
void RawStringExpr__emit_(Expr* self_, Ctx* ctx) {
RawStringExpr* self = (RawStringExpr*)self_;
int index = Ctx__add_const_string(ctx, self->value);
Ctx__emit_(ctx, self->opcode, index, self->line);
}
RawStringExpr* RawStringExpr__new(int line, c11_sv value, Opcode opcode) {
const static ExprVt Vt = {.emit_ = RawStringExpr__emit_};
RawStringExpr* self = PK_MALLOC(sizeof(RawStringExpr));
self->vt = &Vt;
self->line = line;
self->value = value;
self->opcode = opcode;
return self;
}
typedef struct ImagExpr {
EXPR_COMMON_HEADER
double value;
} ImagExpr;
void ImagExpr__emit_(Expr* self_, Ctx* ctx) {
ImagExpr* self = (ImagExpr*)self_;
py_TValue value;
py_newfloat(&value, self->value);
int index = Ctx__add_const(ctx, &value);
Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
Ctx__emit_(ctx, OP_BUILD_IMAG, BC_NOARG, self->line);
}
ImagExpr* ImagExpr__new(int line, double value) {
const static ExprVt Vt = {.emit_ = ImagExpr__emit_};
ImagExpr* self = PK_MALLOC(sizeof(ImagExpr));
self->vt = &Vt;
self->line = line;
self->value = value;
return self;
}
typedef struct LiteralExpr {
EXPR_COMMON_HEADER
const TokenValue* value;
bool negated;
} LiteralExpr;
void LiteralExpr__emit_(Expr* self_, Ctx* ctx) {
LiteralExpr* self = (LiteralExpr*)self_;
switch(self->value->index) {
case TokenValue_I64: {
py_i64 val = self->value->_i64;
if(self->negated) val = -val;
Ctx__emit_int(ctx, val, self->line);
break;
}
case TokenValue_F64: {
py_TValue value;
py_f64 val = self->value->_f64;
if(self->negated) val = -val;
py_newfloat(&value, val);
int index = Ctx__add_const(ctx, &value);
Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
case TokenValue_STR: {
assert(!self->negated);
c11_sv sv = c11_string__sv(self->value->_str);
int index = Ctx__add_const_string(ctx, sv);
Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
default: c11__unreachable();
}
}
LiteralExpr* LiteralExpr__new(int line, const TokenValue* value) {
const static ExprVt Vt = {.emit_ = LiteralExpr__emit_, .is_literal = true};
LiteralExpr* self = PK_MALLOC(sizeof(LiteralExpr));
self->vt = &Vt;
self->line = line;
self->value = value;
self->negated = false;
return self;
}
typedef struct Literal0Expr {
EXPR_COMMON_HEADER
TokenIndex token;
} Literal0Expr;
void Literal0Expr__emit_(Expr* self_, Ctx* ctx) {
Literal0Expr* self = (Literal0Expr*)self_;
Opcode opcode;
switch(self->token) {
case TK_NONE: opcode = OP_LOAD_NONE; break;
case TK_TRUE: opcode = OP_LOAD_TRUE; break;
case TK_FALSE: opcode = OP_LOAD_FALSE; break;
case TK_DOTDOTDOT: opcode = OP_LOAD_ELLIPSIS; break;
default: c11__unreachable();
}
Ctx__emit_(ctx, opcode, BC_NOARG, self->line);
}
Literal0Expr* Literal0Expr__new(int line, TokenIndex token) {
const static ExprVt Vt = {.emit_ = Literal0Expr__emit_};
Literal0Expr* self = PK_MALLOC(sizeof(Literal0Expr));
self->vt = &Vt;
self->line = line;
self->token = token;
return self;
}
typedef struct LoadConstExpr {
EXPR_COMMON_HEADER
int index;
} LoadConstExpr;
void LoadConstExpr__emit_(Expr* self_, Ctx* ctx) {
LoadConstExpr* self = (LoadConstExpr*)self_;
Ctx__emit_(ctx, OP_LOAD_CONST, self->index, self->line);
}
LoadConstExpr* LoadConstExpr__new(int line, int index) {
const static ExprVt Vt = {.emit_ = LoadConstExpr__emit_};
LoadConstExpr* self = PK_MALLOC(sizeof(LoadConstExpr));
self->vt = &Vt;
self->line = line;
self->index = index;
return self;
}
typedef struct SliceExpr {
EXPR_COMMON_HEADER
Expr* start;
Expr* stop;
Expr* step;
} SliceExpr;
void SliceExpr__dtor(Expr* self_) {
SliceExpr* self = (SliceExpr*)self_;
vtdelete(self->start);
vtdelete(self->stop);
vtdelete(self->step);
}
void SliceExpr__emit_(Expr* self_, Ctx* ctx) {
SliceExpr* self = (SliceExpr*)self_;
if(self->start)
vtemit_(self->start, ctx);
else
Ctx__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->stop)
vtemit_(self->stop, ctx);
else
Ctx__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->step)
vtemit_(self->step, ctx);
else
Ctx__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_BUILD_SLICE, BC_NOARG, self->line);
}
SliceExpr* SliceExpr__new(int line) {
const static ExprVt Vt = {.dtor = SliceExpr__dtor, .emit_ = SliceExpr__emit_};
SliceExpr* self = PK_MALLOC(sizeof(SliceExpr));
self->vt = &Vt;
self->line = line;
self->start = NULL;
self->stop = NULL;
self->step = NULL;
return self;
}
typedef struct DictItemExpr {
EXPR_COMMON_HEADER
Expr* key;
Expr* value;
} DictItemExpr;
static void DictItemExpr__dtor(Expr* self_) {
DictItemExpr* self = (DictItemExpr*)self_;
vtdelete(self->key);
vtdelete(self->value);
}
static void DictItemExpr__emit_(Expr* self_, Ctx* ctx) {
DictItemExpr* self = (DictItemExpr*)self_;
vtemit_(self->key, ctx);
vtemit_(self->value, ctx);
}
static DictItemExpr* DictItemExpr__new(int line) {
const static ExprVt Vt = {.dtor = DictItemExpr__dtor, .emit_ = DictItemExpr__emit_};
DictItemExpr* self = PK_MALLOC(sizeof(DictItemExpr));
self->vt = &Vt;
self->line = line;
self->key = NULL;
self->value = NULL;
return self;
}
// ListExpr, DictExpr, SetExpr, TupleExpr
typedef struct SequenceExpr {
EXPR_COMMON_HEADER
Expr** items;
int itemCount;
Opcode opcode;
} SequenceExpr;
static void SequenceExpr__emit_(Expr* self_, Ctx* ctx) {
SequenceExpr* self = (SequenceExpr*)self_;
for(int i = 0; i < self->itemCount; i++) {
Expr* item = self->items[i];
vtemit_(item, ctx);
}
Ctx__emit_(ctx, self->opcode, self->itemCount, self->line);
}
void SequenceExpr__dtor(Expr* self_) {
SequenceExpr* self = (SequenceExpr*)self_;
for(int i = 0; i < self->itemCount; i++) {
vtdelete(self->items[i]);
}
PK_FREE(self->items);
}
bool TupleExpr__emit_store(Expr* self_, Ctx* ctx) {
SequenceExpr* self = (SequenceExpr*)self_;
// TOS is an iterable
// items may contain StarredExpr, we should check it
int starred_i = -1;
for(int i = 0; i < self->itemCount; i++) {
Expr* e = self->items[i];
if(e->vt->is_starred) {
if(((StarredExpr*)e)->level > 0) {
if(starred_i == -1)
starred_i = i;
else
return false; // multiple StarredExpr not allowed
}
}
}
if(starred_i == -1) {
Ctx__emit_(ctx, OP_UNPACK_SEQUENCE, self->itemCount, self->line);
} else {
// starred assignment target must be in a tuple
if(self->itemCount == 1) return false;
// starred assignment target must be the last one (differ from cpython)
if(starred_i != self->itemCount - 1) return false;
// a,*b = [1,2,3]
// stack is [1,2,3] -> [1,[2,3]]
Ctx__emit_(ctx, OP_UNPACK_EX, self->itemCount - 1, self->line);
}
// do reverse emit
for(int i = self->itemCount - 1; i >= 0; i--) {
Expr* e = self->items[i];
bool ok = vtemit_store(e, ctx);
if(!ok) return false;
}
return true;
}
bool TupleExpr__emit_del(Expr* self_, Ctx* ctx) {
SequenceExpr* self = (SequenceExpr*)self_;
for(int i = 0; i < self->itemCount; i++) {
Expr* e = self->items[i];
bool ok = vtemit_del(e, ctx);
if(!ok) return false;
}
return true;
}
static SequenceExpr* SequenceExpr__new(int line, const ExprVt* vt, int count, Opcode opcode) {
SequenceExpr* self = PK_MALLOC(sizeof(SequenceExpr));
self->vt = vt;
self->line = line;
self->opcode = opcode;
self->items = PK_MALLOC(sizeof(Expr*) * count);
self->itemCount = count;
return self;
}
SequenceExpr* FStringExpr__new(int line, int count) {
const static ExprVt ListExprVt = {.dtor = SequenceExpr__dtor, .emit_ = SequenceExpr__emit_};
return SequenceExpr__new(line, &ListExprVt, count, OP_BUILD_STRING);
}
SequenceExpr* ListExpr__new(int line, int count) {
const static ExprVt ListExprVt = {.dtor = SequenceExpr__dtor, .emit_ = SequenceExpr__emit_};
return SequenceExpr__new(line, &ListExprVt, count, OP_BUILD_LIST);
}
SequenceExpr* DictExpr__new(int line, int count) {
const static ExprVt DictExprVt = {.dtor = SequenceExpr__dtor, .emit_ = SequenceExpr__emit_};
return SequenceExpr__new(line, &DictExprVt, count, OP_BUILD_DICT);
}
SequenceExpr* SetExpr__new(int line, int count) {
const static ExprVt SetExprVt = {
.dtor = SequenceExpr__dtor,
.emit_ = SequenceExpr__emit_,
};
return SequenceExpr__new(line, &SetExprVt, count, OP_BUILD_SET);
}
SequenceExpr* TupleExpr__new(int line, int count) {
const static ExprVt TupleExprVt = {.dtor = SequenceExpr__dtor,
.emit_ = SequenceExpr__emit_,
.is_tuple = true,
.emit_store = TupleExpr__emit_store,
.emit_del = TupleExpr__emit_del};
return SequenceExpr__new(line, &TupleExprVt, count, OP_BUILD_TUPLE);
}
typedef struct CompExpr {
EXPR_COMMON_HEADER
Expr* expr; // loop expr
Expr* vars; // loop vars
Expr* iter; // loop iter
Expr* cond; // optional if condition
Opcode op0;
Opcode op1;
} CompExpr;
void CompExpr__dtor(Expr* self_) {
CompExpr* self = (CompExpr*)self_;
vtdelete(self->expr);
vtdelete(self->vars);
vtdelete(self->iter);
vtdelete(self->cond);
}
void CompExpr__emit_(Expr* self_, Ctx* ctx) {
CompExpr* self = (CompExpr*)self_;
Ctx__emit_(ctx, self->op0, 0, self->line);
vtemit_(self->iter, ctx);
Ctx__emit_(ctx, OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
int block = Ctx__enter_block(ctx, CodeBlockType_FOR_LOOP);
int block_start = Ctx__emit_(ctx, OP_FOR_ITER, block, BC_KEEPLINE);
bool ok = vtemit_store(self->vars, ctx);
// this error occurs in `vars` instead of this line, but...nevermind
assert(ok); // this should raise a SyntaxError, but we just assert it
if(self->cond) {
vtemit_(self->cond, ctx);
int patch = Ctx__emit_(ctx, OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
vtemit_(self->expr, ctx);
Ctx__emit_(ctx, self->op1, BC_NOARG, BC_KEEPLINE);
Ctx__patch_jump(ctx, patch);
} else {
vtemit_(self->expr, ctx);
Ctx__emit_(ctx, self->op1, BC_NOARG, BC_KEEPLINE);
}
Ctx__emit_jump(ctx, block_start, BC_KEEPLINE);
Ctx__exit_block(ctx);
}
CompExpr* CompExpr__new(int line, Opcode op0, Opcode op1) {
const static ExprVt Vt = {.dtor = CompExpr__dtor, .emit_ = CompExpr__emit_};
CompExpr* self = PK_MALLOC(sizeof(CompExpr));
self->vt = &Vt;
self->line = line;
self->op0 = op0;
self->op1 = op1;
self->expr = NULL;
self->vars = NULL;
self->iter = NULL;
self->cond = NULL;
return self;
}
typedef struct LambdaExpr {
EXPR_COMMON_HEADER
int index;
} LambdaExpr;
static void LambdaExpr__emit_(Expr* self_, Ctx* ctx) {
LambdaExpr* self = (LambdaExpr*)self_;
Ctx__emit_(ctx, OP_LOAD_FUNCTION, self->index, self->line);
}
LambdaExpr* LambdaExpr__new(int line, int index) {
const static ExprVt Vt = {.emit_ = LambdaExpr__emit_};
LambdaExpr* self = PK_MALLOC(sizeof(LambdaExpr));
self->vt = &Vt;
self->line = line;
self->index = index;
return self;
}
// AndExpr, OrExpr
typedef struct LogicBinaryExpr {
EXPR_COMMON_HEADER
Expr* lhs;
Expr* rhs;
Opcode opcode;
} LogicBinaryExpr;
void LogicBinaryExpr__dtor(Expr* self_) {
LogicBinaryExpr* self = (LogicBinaryExpr*)self_;
vtdelete(self->lhs);
vtdelete(self->rhs);
}
void LogicBinaryExpr__emit_(Expr* self_, Ctx* ctx) {
LogicBinaryExpr* self = (LogicBinaryExpr*)self_;
vtemit_(self->lhs, ctx);
int patch = Ctx__emit_(ctx, self->opcode, BC_NOARG, self->line);
vtemit_(self->rhs, ctx);
Ctx__patch_jump(ctx, patch);
}
LogicBinaryExpr* LogicBinaryExpr__new(int line, Opcode opcode) {
const static ExprVt Vt = {.emit_ = LogicBinaryExpr__emit_, .dtor = LogicBinaryExpr__dtor};
LogicBinaryExpr* self = PK_MALLOC(sizeof(LogicBinaryExpr));
self->vt = &Vt;
self->line = line;
self->lhs = NULL;
self->rhs = NULL;
self->opcode = opcode;
return self;
}
typedef struct GroupedExpr {
EXPR_COMMON_HEADER
Expr* child;
} GroupedExpr;
void GroupedExpr__dtor(Expr* self_) {
GroupedExpr* self = (GroupedExpr*)self_;
vtdelete(self->child);
}
void GroupedExpr__emit_(Expr* self_, Ctx* ctx) {
GroupedExpr* self = (GroupedExpr*)self_;
vtemit_(self->child, ctx);
}
bool GroupedExpr__emit_del(Expr* self_, Ctx* ctx) {
GroupedExpr* self = (GroupedExpr*)self_;
return vtemit_del(self->child, ctx);
}
bool GroupedExpr__emit_store(Expr* self_, Ctx* ctx) {
GroupedExpr* self = (GroupedExpr*)self_;
return vtemit_store(self->child, ctx);
}
GroupedExpr* GroupedExpr__new(int line, Expr* child) {
const static ExprVt Vt = {.dtor = GroupedExpr__dtor,
.emit_ = GroupedExpr__emit_,
.emit_del = GroupedExpr__emit_del,
.emit_store = GroupedExpr__emit_store};
GroupedExpr* self = PK_MALLOC(sizeof(GroupedExpr));
self->vt = &Vt;
self->line = line;
self->child = child;
return self;
}
typedef struct BinaryExpr {
EXPR_COMMON_HEADER
Expr* lhs;
Expr* rhs;
TokenIndex op;
bool inplace;
} BinaryExpr;
static void BinaryExpr__dtor(Expr* self_) {
BinaryExpr* self = (BinaryExpr*)self_;
vtdelete(self->lhs);
vtdelete(self->rhs);
}
static Opcode cmp_token2op(TokenIndex token) {
switch(token) {
case TK_LT: return OP_COMPARE_LT;
case TK_LE: return OP_COMPARE_LE;
case TK_EQ: return OP_COMPARE_EQ;
case TK_NE: return OP_COMPARE_NE;
case TK_GT: return OP_COMPARE_GT;
case TK_GE: return OP_COMPARE_GE;
default: return 0;
}
}
#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2op(((BinaryExpr*)(e))->op))
static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
if(is_compare_expr(self->lhs)) {
_emit_compare((BinaryExpr*)self->lhs, ctx, jmps);
} else {
vtemit_(self->lhs, ctx); // [a]
}
vtemit_(self->rhs, ctx); // [a, b]
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b]
Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b]
Ctx__emit_(ctx, cmp_token2op(self->op), BC_NOARG, self->line);
// [b, RES]
int index = Ctx__emit_(ctx, OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, self->line);
c11_vector__push(int, jmps, index);
}
static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
BinaryExpr* self = (BinaryExpr*)self_;
c11_vector /*T=int*/ jmps;
c11_vector__ctor(&jmps, sizeof(int));
if(cmp_token2op(self->op) && is_compare_expr(self->lhs)) {
// (a < b) < c
BinaryExpr* e = (BinaryExpr*)self->lhs;
_emit_compare(e, ctx, &jmps);
// [b, RES]
} else {
// (1 + 2) < c
if(self->inplace) {
vtemit_inplace(self->lhs, ctx);
} else {
vtemit_(self->lhs, ctx);
}
}
vtemit_(self->rhs, ctx);
Opcode opcode;
uint16_t arg = BC_NOARG;
switch(self->op) {
case TK_ADD: opcode = OP_BINARY_ADD; break;
case TK_SUB: opcode = OP_BINARY_SUB; break;
case TK_MUL: opcode = OP_BINARY_MUL; break;
case TK_DIV: opcode = OP_BINARY_TRUEDIV; break;
case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break;
case TK_MOD: opcode = OP_BINARY_MOD; break;
case TK_POW: opcode = OP_BINARY_POW; break;
case TK_LT: opcode = OP_COMPARE_LT; break;
case TK_LE: opcode = OP_COMPARE_LE; break;
case TK_EQ: opcode = OP_COMPARE_EQ; break;
case TK_NE: opcode = OP_COMPARE_NE; break;
case TK_GT: opcode = OP_COMPARE_GT; break;
case TK_GE: opcode = OP_COMPARE_GE; break;
case TK_IN:
opcode = OP_CONTAINS_OP;
arg = 0;
break;
case TK_NOT_IN:
opcode = OP_CONTAINS_OP;
arg = 1;
break;
case TK_IS:
opcode = OP_IS_OP;
arg = 0;
break;
case TK_IS_NOT:
opcode = OP_IS_OP;
arg = 1;
break;
case TK_LSHIFT: opcode = OP_BINARY_LSHIFT; break;
case TK_RSHIFT: opcode = OP_BINARY_RSHIFT; break;
case TK_AND: opcode = OP_BINARY_AND; break;
case TK_OR: opcode = OP_BINARY_OR; break;
case TK_XOR: opcode = OP_BINARY_XOR; break;
case TK_DECORATOR: opcode = OP_BINARY_MATMUL; break;
default: c11__unreachable();
}
Ctx__emit_(ctx, opcode, arg, self->line);
for(int i = 0; i < jmps.length; i++) {
Ctx__patch_jump(ctx, c11__getitem(int, &jmps, i));
}
c11_vector__dtor(&jmps);
}
BinaryExpr* BinaryExpr__new(int line, TokenIndex op, bool inplace) {
const static ExprVt Vt = {.emit_ = BinaryExpr__emit_,
.dtor = BinaryExpr__dtor,
.is_binary = true};
BinaryExpr* self = PK_MALLOC(sizeof(BinaryExpr));
self->vt = &Vt;
self->line = line;
self->lhs = NULL;
self->rhs = NULL;
self->op = op;
self->inplace = inplace;
return self;
}
typedef struct TernaryExpr {
EXPR_COMMON_HEADER
Expr* cond;
Expr* true_expr;
Expr* false_expr;
} TernaryExpr;
void TernaryExpr__dtor(Expr* self_) {
TernaryExpr* self = (TernaryExpr*)self_;
vtdelete(self->cond);
vtdelete(self->true_expr);
vtdelete(self->false_expr);
}
void TernaryExpr__emit_(Expr* self_, Ctx* ctx) {
TernaryExpr* self = (TernaryExpr*)self_;
vtemit_(self->cond, ctx);
int patch = Ctx__emit_(ctx, OP_POP_JUMP_IF_FALSE, BC_NOARG, self->cond->line);
vtemit_(self->true_expr, ctx);
int patch_2 = Ctx__emit_(ctx, OP_JUMP_FORWARD, BC_NOARG, self->true_expr->line);
Ctx__patch_jump(ctx, patch);
vtemit_(self->false_expr, ctx);
Ctx__patch_jump(ctx, patch_2);
}
TernaryExpr* TernaryExpr__new(int line) {
const static ExprVt Vt = {
.dtor = TernaryExpr__dtor,
.emit_ = TernaryExpr__emit_,
.is_ternary = true,
};
TernaryExpr* self = PK_MALLOC(sizeof(TernaryExpr));
self->vt = &Vt;
self->line = line;
self->cond = NULL;
self->true_expr = NULL;
self->false_expr = NULL;
return self;
}
typedef struct SubscrExpr {
EXPR_COMMON_HEADER
Expr* lhs;
Expr* rhs;
} SubscrExpr;
void SubscrExpr__dtor(Expr* self_) {
SubscrExpr* self = (SubscrExpr*)self_;
vtdelete(self->lhs);
vtdelete(self->rhs);
}
void SubscrExpr__emit_(Expr* self_, Ctx* ctx) {
SubscrExpr* self = (SubscrExpr*)self_;
vtemit_(self->lhs, ctx);
vtemit_(self->rhs, ctx);
Ctx__emit_(ctx, OP_LOAD_SUBSCR, BC_NOARG, self->line);
}
bool SubscrExpr__emit_store(Expr* self_, Ctx* ctx) {
SubscrExpr* self = (SubscrExpr*)self_;
vtemit_(self->lhs, ctx);
vtemit_(self->rhs, ctx);
Ctx__emit_(ctx, OP_STORE_SUBSCR, BC_NOARG, self->line);
return true;
}
void SubscrExpr__emit_inplace(Expr* self_, Ctx* ctx) {
SubscrExpr* self = (SubscrExpr*)self_;
vtemit_(self->lhs, ctx);
vtemit_(self->rhs, ctx);
Ctx__emit_(ctx, OP_DUP_TOP_TWO, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_LOAD_SUBSCR, BC_NOARG, self->line);
}
bool SubscrExpr__emit_istore(Expr* self_, Ctx* ctx) {
SubscrExpr* self = (SubscrExpr*)self_;
// [a, b, val] -> [val, a, b]
Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_STORE_SUBSCR, BC_NOARG, self->line);
return true;
}
bool SubscrExpr__emit_del(Expr* self_, Ctx* ctx) {
SubscrExpr* self = (SubscrExpr*)self_;
vtemit_(self->lhs, ctx);
vtemit_(self->rhs, ctx);
Ctx__emit_(ctx, OP_DELETE_SUBSCR, BC_NOARG, self->line);
return true;
}
SubscrExpr* SubscrExpr__new(int line) {
const static ExprVt Vt = {
.dtor = SubscrExpr__dtor,
.emit_ = SubscrExpr__emit_,
.emit_store = SubscrExpr__emit_store,
.emit_inplace = SubscrExpr__emit_inplace,
.emit_istore = SubscrExpr__emit_istore,
.emit_del = SubscrExpr__emit_del,
.is_subscr = true,
};
SubscrExpr* self = PK_MALLOC(sizeof(SubscrExpr));
self->vt = &Vt;
self->line = line;
self->lhs = NULL;
self->rhs = NULL;
return self;
}
typedef struct AttribExpr {
EXPR_COMMON_HEADER
Expr* child;
py_Name name;
} AttribExpr;
void AttribExpr__dtor(Expr* self_) {
AttribExpr* self = (AttribExpr*)self_;
vtdelete(self->child);
}
void AttribExpr__emit_(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_LOAD_ATTR, Ctx__add_name(ctx, self->name), self->line);
}
bool AttribExpr__emit_del(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_DELETE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true;
}
bool AttribExpr__emit_store(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_STORE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true;
}
void AttribExpr__emit_inplace(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_LOAD_ATTR, Ctx__add_name(ctx, self->name), self->line);
}
bool AttribExpr__emit_istore(Expr* self_, Ctx* ctx) {
// [a, val] -> [val, a]
AttribExpr* self = (AttribExpr*)self_;
Ctx__emit_(ctx, OP_ROT_TWO, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_STORE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true;
}
AttribExpr* AttribExpr__new(int line, Expr* child, py_Name name) {
const static ExprVt Vt = {.emit_ = AttribExpr__emit_,
.emit_del = AttribExpr__emit_del,
.emit_store = AttribExpr__emit_store,
.emit_inplace = AttribExpr__emit_inplace,
.emit_istore = AttribExpr__emit_istore,
.dtor = AttribExpr__dtor,
.is_attrib = true};
AttribExpr* self = PK_MALLOC(sizeof(AttribExpr));
self->vt = &Vt;
self->line = line;
self->child = child;
self->name = name;
return self;
}
typedef struct CallExprKwArg {
py_Name key;
Expr* val;
} CallExprKwArg;
typedef struct CallExpr {
EXPR_COMMON_HEADER
Expr* callable;
c11_vector /*T=Expr* */ args;
// **a will be interpreted as a special keyword argument: {{0}: a}
c11_vector /*T=CallExprKwArg */ kwargs;
} CallExpr;
void CallExpr__dtor(Expr* self_) {
CallExpr* self = (CallExpr*)self_;
vtdelete(self->callable);
c11__foreach(Expr*, &self->args, e) vtdelete(*e);
c11__foreach(CallExprKwArg, &self->kwargs, e) vtdelete(e->val);
c11_vector__dtor(&self->args);
c11_vector__dtor(&self->kwargs);
}
void CallExpr__emit_(Expr* self_, Ctx* ctx) {
CallExpr* self = (CallExpr*)self_;
bool vargs = false; // whether there is *args as input
bool vkwargs = false; // whether there is **kwargs as input
c11__foreach(Expr*, &self->args, e) {
if((*e)->vt->is_starred) vargs = true;
}
c11__foreach(CallExprKwArg, &self->kwargs, e) {
if(e->val->vt->is_starred) vkwargs = true;
}
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod`
if(self->callable->vt->is_attrib) {
AttribExpr* p = (AttribExpr*)self->callable;
vtemit_(p->child, ctx);
Ctx__emit_(ctx, OP_LOAD_METHOD, Ctx__add_name(ctx, p->name), p->line);
} else {
vtemit_(self->callable, ctx);
Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
}
Opcode opcode = OP_CALL;
if(vargs || vkwargs) {
// in this case, there is at least one *args or **kwargs as StarredExpr
// OP_CALL_VARGS needs to unpack them via vectorcall_buffer
opcode = OP_CALL_VARGS;
}
c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); }
c11__foreach(CallExprKwArg, &self->kwargs, e) {
if(e->key == 0) {
// special key for **kwargs
Ctx__emit_int(ctx, 0, self->line);
} else {
Ctx__emit_name(ctx, e->key, self->line);
}
vtemit_(e->val, ctx);
}
int KWARGC = self->kwargs.length;
int ARGC = self->args.length;
assert(KWARGC < 256 && ARGC < 256);
Ctx__emit_(ctx, opcode, (KWARGC << 8) | ARGC, self->line);
}
CallExpr* CallExpr__new(int line, Expr* callable) {
const static ExprVt Vt = {.dtor = CallExpr__dtor, .emit_ = CallExpr__emit_};
CallExpr* self = PK_MALLOC(sizeof(CallExpr));
self->vt = &Vt;
self->line = line;
self->callable = callable;
c11_vector__ctor(&self->args, sizeof(Expr*));
c11_vector__ctor(&self->kwargs, sizeof(CallExprKwArg));
return self;
}
/* context.c */
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) {
self->co = co;
self->func = func;
self->level = level;
self->curr_iblock = 0;
self->is_compiling_class = false;
c11_vector__ctor(&self->s_expr, sizeof(Expr*));
c11_smallmap_n2d__ctor(&self->global_names);
c11_smallmap_v2d__ctor(&self->co_consts_string_dedup_map);
}
static void Ctx__dtor(Ctx* self) {
// clean the expr stack
for(int i = 0; i < self->s_expr.length; i++) {
vtdelete(c11__getitem(Expr*, &self->s_expr, i));
}
c11_vector__dtor(&self->s_expr);
c11_smallmap_n2d__dtor(&self->global_names);
// free the dedup map
c11__foreach(c11_smallmap_v2d_KV, &self->co_consts_string_dedup_map, p_kv) {
const char* p = p_kv->key.data;
PK_FREE((void*)p);
}
c11_smallmap_v2d__dtor(&self->co_consts_string_dedup_map);
}
static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break) {
int index = self->curr_iblock;
while(index >= 0) {
CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, index);
switch(block->type) {
case CodeBlockType_WHILE_LOOP: return index;
case CodeBlockType_FOR_LOOP: {
if(is_break) Ctx__emit_(self, OP_POP_TOP, BC_NOARG, line);
return index;
}
case CodeBlockType_WITH: {
Ctx__emit_(self, OP_POP_TOP, BC_NOARG, line);
break;
}
case CodeBlockType_TRY: {
Ctx__emit_(self, OP_END_TRY, BC_NOARG, line);
break;
}
case CodeBlockType_EXCEPT: {
Ctx__emit_(self, OP_END_TRY, BC_NOARG, line);
break;
}
default: break;
}
index = block->parent;
}
return index;
}
static int Ctx__enter_block(Ctx* self, CodeBlockType type) {
CodeBlock block = {type, self->curr_iblock, self->co->codes.length, -1, -1};
c11_vector__push(CodeBlock, &self->co->blocks, block);
self->curr_iblock = self->co->blocks.length - 1;
return self->curr_iblock;
}
static void Ctx__exit_block(Ctx* self) {
CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, self->curr_iblock);
block->end = self->co->codes.length;
self->curr_iblock = block->parent;
assert(self->curr_iblock >= 0);
}
static void Ctx__s_emit_decorators(Ctx* self, int count) {
if(count == 0) return;
assert(Ctx__s_size(self) >= count);
// [obj]
for(int i = 0; i < count; i++) {
Expr* deco = Ctx__s_popx(self);
vtemit_(deco, self); // [obj, f]
Ctx__emit_(self, OP_ROT_TWO, BC_NOARG, deco->line); // [f, obj]
Ctx__emit_(self, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); // [f, obj, NULL]
Ctx__emit_(self, OP_ROT_TWO, BC_NOARG, BC_KEEPLINE); // [obj, NULL, f]
Ctx__emit_(self, OP_CALL, 1, deco->line); // [obj]
vtdelete(deco);
}
}
static int Ctx__emit_(Ctx* self, Opcode opcode, uint16_t arg, int line) {
Bytecode bc = {(uint16_t)opcode, arg};
BytecodeEx bcx = {line, self->curr_iblock};
c11_vector__push(Bytecode, &self->co->codes, bc);
c11_vector__push(BytecodeEx, &self->co->codes_ex, bcx);
int i = self->co->codes.length - 1;
BytecodeEx* codes_ex = (BytecodeEx*)self->co->codes_ex.data;
if(line == BC_KEEPLINE) { codes_ex[i].lineno = i >= 1 ? codes_ex[i - 1].lineno : 1; }
return i;
}
static int Ctx__emit_int(Ctx* self, int64_t value, int line) {
if(INT16_MIN <= value && value <= INT16_MAX) {
return Ctx__emit_(self, OP_LOAD_SMALL_INT, (uint16_t)value, line);
} else {
py_TValue tmp;
py_newint(&tmp, value);
return Ctx__emit_(self, OP_LOAD_CONST, Ctx__add_const(self, &tmp), line);
}
}
static int Ctx__emit_name(Ctx* self, py_Name name, int line) {
int index = Ctx__add_name(self, name);
assert(index <= UINT16_MAX);
return Ctx__emit_(self, OP_LOAD_NAME_AS_INT, (uint16_t)index, line);
}
static void Ctx__patch_jump(Ctx* self, int index) {
Bytecode* co_codes = (Bytecode*)self->co->codes.data;
int target = self->co->codes.length;
Bytecode__set_signed_arg(&co_codes[index], target - index);
}
static void Ctx__emit_jump(Ctx* self, int target, int line) {
int index = Ctx__emit_(self, OP_JUMP_FORWARD, BC_NOARG, line);
// should place after Ctx__emit_ because of realloc
Bytecode* co_codes = (Bytecode*)self->co->codes.data;
Bytecode__set_signed_arg(&co_codes[index], target - index);
}
static int Ctx__add_varname(Ctx* self, py_Name name) {
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
return CodeObject__add_varname(self->co, name);
}
static int Ctx__add_name(Ctx* self, py_Name name) {
assert(name != 0);
return CodeObject__add_name(self->co, name);
}
static int Ctx__add_const_string(Ctx* self, c11_sv key) {
if(key.size > 100) {
py_Ref tmp = c11_vector__emplace(&self->co->consts);
py_newstrv(tmp, key);
int index = self->co->consts.length - 1;
return index;
}
int* val = c11_smallmap_v2d__try_get(&self->co_consts_string_dedup_map, key);
if(val) {
return *val;
} else {
py_Ref tmp = c11_vector__emplace(&self->co->consts);
py_newstrv(tmp, key);
int index = self->co->consts.length - 1;
// dedup
char* new_buf = PK_MALLOC(key.size + 1);
memcpy(new_buf, key.data, key.size);
new_buf[key.size] = 0;
c11_smallmap_v2d__set(&self->co_consts_string_dedup_map,
(c11_sv){new_buf, key.size},
index);
return index;
}
}
static int Ctx__add_const(Ctx* self, py_Ref v) {
assert(v->type != tp_str);
c11_vector__push(py_TValue, &self->co->consts, *v);
return self->co->consts.length - 1;
}
static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int line) {
if(name == py_name("_")) {
Ctx__emit_(self, OP_POP_TOP, BC_NOARG, line);
return;
}
switch(scope) {
case NAME_LOCAL: Ctx__emit_(self, OP_STORE_FAST, Ctx__add_varname(self, name), line); break;
case NAME_GLOBAL: {
Opcode op = self->co->src->is_dynamic ? OP_STORE_NAME : OP_STORE_GLOBAL;
Ctx__emit_(self, op, Ctx__add_name(self, name), line);
} break;
default: c11__unreachable();
}
}
// emit top -> pop -> delete
static void Ctx__s_emit_top(Ctx* self) {
assert(self->s_expr.length);
Expr* top = c11_vector__back(Expr*, &self->s_expr);
vtemit_(top, self);
vtdelete(top);
c11_vector__pop(&self->s_expr);
}
// push
static void Ctx__s_push(Ctx* self, Expr* expr) { c11_vector__push(Expr*, &self->s_expr, expr); }
// top
static Expr* Ctx__s_top(Ctx* self) {
assert(self->s_expr.length);
return c11_vector__back(Expr*, &self->s_expr);
}
// size
static int Ctx__s_size(Ctx* self) { return self->s_expr.length; }
// pop -> delete
static void Ctx__s_pop(Ctx* self) {
assert(self->s_expr.length);
Expr* top = c11_vector__back(Expr*, &self->s_expr);
vtdelete(top);
c11_vector__pop(&self->s_expr);
}
// pop move
static Expr* Ctx__s_popx(Ctx* self) {
assert(self->s_expr.length);
Expr* top = c11_vector__back(Expr*, &self->s_expr);
c11_vector__pop(&self->s_expr);
return top;
}
/* compiler.c */
typedef struct Compiler Compiler;
typedef Error* (*PrattCallback)(Compiler* self);
typedef struct PrattRule {
PrattCallback prefix;
PrattCallback infix;
enum Precedence precedence;
} PrattRule;
const static PrattRule rules[TK__COUNT__];
typedef struct Compiler {
SourceData_ src; // weakref
Token* tokens;
int tokens_length;
int i; // current token index
c11_vector /*T=CodeEmitContext*/ contexts;
} Compiler;
static void Compiler__ctor(Compiler* self, SourceData_ src, Token* tokens, int tokens_length) {
self->src = src;
self->tokens = tokens;
self->tokens_length = tokens_length;
self->i = 0;
c11_vector__ctor(&self->contexts, sizeof(Ctx));
}
static void Compiler__dtor(Compiler* self) {
// free tokens
for(int i = 0; i < self->tokens_length; i++) {
if(self->tokens[i].value.index == TokenValue_STR) {
// PK_FREE internal string
c11_string__delete(self->tokens[i].value._str);
}
}
PK_FREE(self->tokens);
// free contexts
c11__foreach(Ctx, &self->contexts, ctx) Ctx__dtor(ctx);
c11_vector__dtor(&self->contexts);
}
/**************************************/
#define tk(i) (&self->tokens[i])
#define prev() (&self->tokens[self->i - 1])
#define curr() (&self->tokens[self->i])
#define next() (&self->tokens[self->i + 1])
#define advance() self->i++
#define mode() self->src->mode
#define ctx() (&c11_vector__back(Ctx, &self->contexts))
#define match_newlines() match_newlines_impl(self)
#define consume(expected) \
if(!match(expected)) \
return SyntaxError(self, \
"expected '%s', got '%s'", \
TokenSymbols[expected], \
TokenSymbols[curr()->type]);
#define consume_end_stmt() \
if(!match_end_stmt(self)) return SyntaxError(self, "expected statement end")
#define check(B) \
if((err = B)) return err
static NameScope name_scope(Compiler* self) {
return self->contexts.length > 1 ? NAME_LOCAL : NAME_GLOBAL;
}
Error* SyntaxError(Compiler* self, const char* fmt, ...) {
Error* err = PK_MALLOC(sizeof(Error));
err->src = self->src;
PK_INCREF(self->src);
Token* t = self->i == self->tokens_length ? prev() : curr();
err->lineno = t->line;
va_list args;
va_start(args, fmt);
vsnprintf(err->msg, sizeof(err->msg), fmt, args);
va_end(args);
return err;
}
/* Matchers */
static bool is_expression(Compiler* self, bool allow_slice) {
PrattCallback prefix = rules[curr()->type].prefix;
return prefix && (allow_slice || curr()->type != TK_COLON);
}
#define match(expected) (curr()->type == expected ? (++self->i) : 0)
static bool match_id_by_str(Compiler* self, const char* name) {
if(curr()->type == TK_ID) {
bool ok = c11__sveq2(Token__sv(curr()), name);
if(ok) advance();
return ok;
}
return false;
}
static bool match_newlines_impl(Compiler* self) {
bool consumed = false;
if(curr()->type == TK_EOL) {
while(curr()->type == TK_EOL)
advance();
consumed = true;
}
return consumed;
}
static bool match_end_stmt(Compiler* self) {
if(match(TK_SEMICOLON)) {
match_newlines();
return true;
}
if(match_newlines() || curr()->type == TK_EOF) return true;
if(curr()->type == TK_DEDENT) return true;
return false;
}
/* Expression */
/// Parse an expression and push it onto the stack.
static Error* parse_expression(Compiler* self, int precedence, bool allow_slice) {
PrattCallback prefix = rules[curr()->type].prefix;
if(!prefix || (curr()->type == TK_COLON && !allow_slice)) {
return SyntaxError(self, "expected an expression, got %s", TokenSymbols[curr()->type]);
}
advance();
Error* err;
check(prefix(self));
while(rules[curr()->type].precedence >= precedence &&
(allow_slice || curr()->type != TK_COLON)) {
TokenIndex op = curr()->type;
advance();
PrattCallback infix = rules[op].infix;
if(infix == NULL) {
return SyntaxError(self, "expected an infix operator, got %s", TokenSymbols[op]);
}
check(infix(self));
}
return NULL;
}
static Error* EXPR_TUPLE_ALLOW_SLICE(Compiler* self, bool allow_slice) {
Error* err;
check(parse_expression(self, PREC_LOWEST + 1, allow_slice));
if(!match(TK_COMMA)) return NULL;
// tuple expression // (a, )
int count = 1;
do {
if(!is_expression(self, allow_slice)) break;
check(parse_expression(self, PREC_LOWEST + 1, allow_slice));
count += 1;
} while(match(TK_COMMA));
// pop `count` expressions from the stack and merge them into a TupleExpr
SequenceExpr* e = TupleExpr__new(prev()->line, count);
for(int i = count - 1; i >= 0; i--) {
e->items[i] = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
/// Parse a simple expression.
static Error* EXPR(Compiler* self) { return parse_expression(self, PREC_LOWEST + 1, false); }
/// Parse a simple expression or a tuple of expressions.
static Error* EXPR_TUPLE(Compiler* self) { return EXPR_TUPLE_ALLOW_SLICE(self, false); }
// special case for `for loop` and `comp`
static Error* EXPR_VARS(Compiler* self) {
int count = 0;
do {
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
NameExpr* e = NameExpr__new(prev()->line, name, name_scope(self));
Ctx__s_push(ctx(), (Expr*)e);
count += 1;
} while(match(TK_COMMA));
if(count > 1) {
SequenceExpr* e = TupleExpr__new(prev()->line, count);
for(int i = count - 1; i >= 0; i--) {
e->items[i] = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e);
}
return NULL;
}
/* Misc */
static void push_global_context(Compiler* self, CodeObject* co) {
co->start_line = self->i == 0 ? 1 : prev()->line;
Ctx* ctx = c11_vector__emplace(&self->contexts);
Ctx__ctor(ctx, co, NULL, self->contexts.length);
}
static Error* pop_context(Compiler* self) {
// add a `return None` in the end as a guard
// previously, we only do this if the last opcode is not a return
// however, this is buggy...since there may be a jump to the end (out of bound) even if the last
// opcode is a return
Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_RETURN_VIRTUAL, BC_KEEPLINE);
CodeObject* co = ctx()->co;
// find the last valid token
int j = self->i - 1;
while(tk(j)->type == TK_EOL || tk(j)->type == TK_DEDENT || tk(j)->type == TK_EOF)
j--;
co->end_line = tk(j)->line;
// some check here
c11_vector* codes = &co->codes;
if(co->nlocals > PK_MAX_CO_VARNAMES) {
return SyntaxError(self, "maximum number of local variables exceeded");
}
if(co->consts.length > 65530) {
return SyntaxError(self, "maximum number of constants exceeded");
}
// pre-compute block.end or block.end2
for(int i = 0; i < codes->length; i++) {
Bytecode* bc = c11__at(Bytecode, codes, i);
if(bc->op == OP_LOOP_CONTINUE) {
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc->arg);
Bytecode__set_signed_arg(bc, block->start - i);
} else if(bc->op == OP_LOOP_BREAK) {
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc->arg);
Bytecode__set_signed_arg(bc, (block->end2 != -1 ? block->end2 : block->end) - i);
} else if(bc->op == OP_FOR_ITER || bc->op == OP_FOR_ITER_YIELD_VALUE) {
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc->arg);
Bytecode__set_signed_arg(bc, block->end - i);
}
}
// pre-compute func->is_simple
FuncDecl* func = ctx()->func;
if(func) {
// check generator
Bytecode* codes = func->code.codes.data;
int codes_length = func->code.codes.length;
for(int i = 0; i < codes_length; i++) {
if(codes[i].op == OP_YIELD_VALUE || codes[i].op == OP_FOR_ITER_YIELD_VALUE) {
func->type = FuncType_GENERATOR;
break;
}
}
if(func->type == FuncType_UNSET) {
bool is_simple = true;
if(func->kwargs.length > 0) is_simple = false;
if(func->starred_arg >= 0) is_simple = false;
if(func->starred_kwarg >= 0) is_simple = false;
if(is_simple) {
func->type = FuncType_SIMPLE;
} else {
func->type = FuncType_NORMAL;
}
}
assert(func->type != FuncType_UNSET);
}
Ctx__dtor(ctx());
c11_vector__pop(&self->contexts);
return NULL;
}
/* Expression Callbacks */
static Error* exprLiteral(Compiler* self) {
LiteralExpr* e = LiteralExpr__new(prev()->line, &prev()->value);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprBytes(Compiler* self) {
c11_sv sv = c11_string__sv(prev()->value._str);
Ctx__s_push(ctx(), (Expr*)RawStringExpr__new(prev()->line, sv, OP_BUILD_BYTES));
return NULL;
}
static Error* exprFString(Compiler* self) {
// @fstr-begin, [@fstr-cpnt | <expr>]*, @fstr-end
int count = 0;
int line = prev()->line;
while(true) {
if(match(TK_FSTR_END)) {
SequenceExpr* e = FStringExpr__new(line, count);
for(int i = count - 1; i >= 0; i--) {
e->items[i] = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
} else if(match(TK_FSTR_CPNT)) {
// OP_LOAD_CONST
LiteralExpr* e = LiteralExpr__new(prev()->line, &prev()->value);
Ctx__s_push(ctx(), (Expr*)e);
count++;
} else {
// {a!r:.2f}
Error* err = EXPR(self);
if(err) return err;
count++;
if(match(TK_FSTR_SPEC)) {
c11_sv spec = Token__sv(prev());
// ':.2f}' -> ':.2f'
spec.size--;
Expr* child = Ctx__s_popx(ctx());
FStringSpecExpr* e = FStringSpecExpr__new(prev()->line, child, spec);
Ctx__s_push(ctx(), (Expr*)e);
}
}
}
}
static Error* exprImag(Compiler* self) {
Ctx__s_push(ctx(), (Expr*)ImagExpr__new(prev()->line, prev()->value._f64));
return NULL;
}
static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index);
static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool is_lambda);
static Error* exprLambda(Compiler* self) {
Error* err;
int line = prev()->line;
int decl_index;
FuncDecl_ decl = push_f_context(self, (c11_sv){"<lambda>", 8}, &decl_index);
if(!match(TK_COLON)) {
check(_compile_f_args(self, decl, true));
consume(TK_COLON);
}
// https://github.com/pocketpy/pocketpy/issues/37
check(parse_expression(self, PREC_LAMBDA + 1, false));
Ctx__s_emit_top(ctx());
Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
check(pop_context(self));
LambdaExpr* e = LambdaExpr__new(line, decl_index);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprOr(Compiler* self) {
Error* err;
int line = prev()->line;
check(parse_expression(self, PREC_LOGICAL_OR + 1, false));
LogicBinaryExpr* e = LogicBinaryExpr__new(line, OP_JUMP_IF_TRUE_OR_POP);
e->rhs = Ctx__s_popx(ctx());
e->lhs = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprAnd(Compiler* self) {
Error* err;
int line = prev()->line;
check(parse_expression(self, PREC_LOGICAL_AND + 1, false));
LogicBinaryExpr* e = LogicBinaryExpr__new(line, OP_JUMP_IF_FALSE_OR_POP);
e->rhs = Ctx__s_popx(ctx());
e->lhs = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprTernary(Compiler* self) {
// [true_expr]
Error* err;
int line = prev()->line;
check(parse_expression(self, PREC_TERNARY + 1, false)); // [true_expr, cond]
consume(TK_ELSE);
check(parse_expression(self, PREC_TERNARY + 1, false)); // [true_expr, cond, false_expr]
TernaryExpr* e = TernaryExpr__new(line);
e->false_expr = Ctx__s_popx(ctx());
e->cond = Ctx__s_popx(ctx());
e->true_expr = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)e);
if(e->cond->vt->is_ternary || e->false_expr->vt->is_ternary || e->true_expr->vt->is_ternary) {
return SyntaxError(self, "nested ternary expressions without `()` are ambiguous");
}
return NULL;
}
static Error* exprBinaryOp(Compiler* self) {
Error* err;
int line = prev()->line;
TokenIndex op = prev()->type;
int precedence = rules[op].precedence;
if(op != TK_POW) {
// if not right associative, increase precedence
precedence += 1;
}
check(parse_expression(self, precedence, false));
BinaryExpr* e = BinaryExpr__new(line, op, false);
if(op == TK_IN || op == TK_NOT_IN) {
e->lhs = Ctx__s_popx(ctx());
e->rhs = Ctx__s_popx(ctx());
} else {
e->rhs = Ctx__s_popx(ctx());
e->lhs = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprNot(Compiler* self) {
Error* err;
int line = prev()->line;
check(parse_expression(self, PREC_LOGICAL_NOT + 1, false));
UnaryExpr* e = UnaryExpr__new(line, Ctx__s_popx(ctx()), OP_UNARY_NOT);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprUnaryOp(Compiler* self) {
Error* err;
int line = prev()->line;
TokenIndex op = prev()->type;
check(parse_expression(self, PREC_UNARY + 1, false));
Expr* e = Ctx__s_popx(ctx());
switch(op) {
case TK_SUB: {
// constant fold
if(e->vt->is_literal) {
LiteralExpr* le = (LiteralExpr*)e;
if(le->value->index == TokenValue_I64 || le->value->index == TokenValue_F64) {
le->negated = true;
}
Ctx__s_push(ctx(), e);
} else {
Ctx__s_push(ctx(), (Expr*)UnaryExpr__new(line, e, OP_UNARY_NEGATIVE));
}
break;
}
case TK_INVERT: Ctx__s_push(ctx(), (Expr*)UnaryExpr__new(line, e, OP_UNARY_INVERT)); break;
case TK_MUL: Ctx__s_push(ctx(), (Expr*)StarredExpr__new(line, e, 1)); break;
case TK_POW: Ctx__s_push(ctx(), (Expr*)StarredExpr__new(line, e, 2)); break;
default: assert(false);
}
return NULL;
}
static Error* exprGroup(Compiler* self) {
Error* err;
int line = prev()->line;
if(match(TK_RPAREN)) {
// empty tuple
Ctx__s_push(ctx(), (Expr*)TupleExpr__new(line, 0));
return NULL;
}
check(EXPR_TUPLE(self)); // () is just for change precedence
consume(TK_RPAREN);
if(Ctx__s_top(ctx())->vt->is_tuple) return NULL;
GroupedExpr* g = GroupedExpr__new(line, Ctx__s_popx(ctx()));
Ctx__s_push(ctx(), (Expr*)g);
return NULL;
}
static Error* exprName(Compiler* self) {
py_Name name = py_namev(Token__sv(prev()));
NameScope scope = name_scope(self);
// promote this name to global scope if needed
if(c11_smallmap_n2d__contains(&ctx()->global_names, name)) {
if(self->src->is_dynamic) return SyntaxError(self, "cannot use global keyword here");
scope = NAME_GLOBAL;
}
NameExpr* e = NameExpr__new(prev()->line, name, scope);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprAttrib(Compiler* self) {
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
AttribExpr* e = AttribExpr__new(prev()->line, Ctx__s_popx(ctx()), name);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprLiteral0(Compiler* self) {
Literal0Expr* e = Literal0Expr__new(prev()->line, prev()->type);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) {
// [expr]
Error* err;
int line = prev()->line;
bool has_cond = false;
check(EXPR_VARS(self)); // [expr, vars]
consume(TK_IN);
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter]
if(match(TK_IF)) {
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter, cond]
has_cond = true;
}
CompExpr* ce = CompExpr__new(line, op0, op1);
if(has_cond) ce->cond = Ctx__s_popx(ctx());
ce->iter = Ctx__s_popx(ctx());
ce->vars = Ctx__s_popx(ctx());
ce->expr = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)ce);
return NULL;
}
static Error* exprList(Compiler* self) {
Error* err;
int line = prev()->line;
int count = 0;
do {
if(curr()->type == TK_RBRACKET) break;
check(EXPR(self));
count += 1;
if(count == 1 && match(TK_FOR)) {
check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND));
consume(TK_RBRACKET);
return NULL;
}
} while(match(TK_COMMA));
consume(TK_RBRACKET);
SequenceExpr* e = ListExpr__new(line, count);
for(int i = count - 1; i >= 0; i--) {
e->items[i] = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
static Error* exprMap(Compiler* self) {
Error* err;
int line = prev()->line;
bool parsing_dict = false; // {...} may be dict or set
int count = 0;
do {
if(curr()->type == TK_RBRACE) break;
check(EXPR(self)); // [key]
if(curr()->type == TK_COLON) { parsing_dict = true; }
if(parsing_dict) {
consume(TK_COLON);
check(EXPR(self)); // [key, value] -> [item]
DictItemExpr* item = DictItemExpr__new(prev()->line);
item->value = Ctx__s_popx(ctx());
item->key = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)item);
}
count += 1; // key-value pair count
if(count == 1 && match(TK_FOR)) {
if(parsing_dict) {
check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD));
} else {
check(consume_comp(self, OP_BUILD_SET, OP_SET_ADD));
}
consume(TK_RBRACE);
return NULL;
}
} while(match(TK_COMMA));
consume(TK_RBRACE);
SequenceExpr* se;
if(count == 0 || parsing_dict) {
se = DictExpr__new(line, count);
} else {
se = SetExpr__new(line, count);
}
for(int i = count - 1; i >= 0; i--) {
se->items[i] = Ctx__s_popx(ctx());
}
Ctx__s_push(ctx(), (Expr*)se);
return NULL;
}
static Error* read_literal(Compiler* self, py_Ref out);
static Error* exprCall(Compiler* self) {
Error* err;
Expr* callable = Ctx__s_popx(ctx());
int line = prev()->line;
CallExpr* e = CallExpr__new(line, callable);
Ctx__s_push(ctx(), (Expr*)e); // push onto the stack in advance
do {
if(curr()->type == TK_RPAREN) break;
if(curr()->type == TK_ID && next()->type == TK_ASSIGN) {
consume(TK_ID);
py_Name key = py_namev(Token__sv(prev()));
consume(TK_ASSIGN);
check(EXPR(self));
CallExprKwArg kw = {key, Ctx__s_popx(ctx())};
c11_vector__push(CallExprKwArg, &e->kwargs, kw);
} else {
check(EXPR(self));
int star_level = 0;
Expr* top = Ctx__s_top(ctx());
if(top->vt->is_starred) star_level = ((StarredExpr*)top)->level;
if(star_level == 2) {
// **kwargs
CallExprKwArg kw = {0, Ctx__s_popx(ctx())};
c11_vector__push(CallExprKwArg, &e->kwargs, kw);
} else {
// positional argument
if(e->kwargs.length > 0) {
return SyntaxError(self, "positional argument follows keyword argument");
}
c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx()));
}
}
} while(match(TK_COMMA));
consume(TK_RPAREN);
return NULL;
}
static Error* exprSlice0(Compiler* self) {
Error* err;
SliceExpr* slice = SliceExpr__new(prev()->line);
Ctx__s_push(ctx(), (Expr*)slice); // push onto the stack in advance
if(is_expression(self, false)) { // :<stop>
check(EXPR(self));
slice->stop = Ctx__s_popx(ctx());
// try optional step
if(match(TK_COLON)) { // :<stop>:<step>
check(EXPR(self));
slice->step = Ctx__s_popx(ctx());
}
} else if(match(TK_COLON)) {
if(is_expression(self, false)) { // ::<step>
check(EXPR(self));
slice->step = Ctx__s_popx(ctx());
} // else ::
} // else :
return NULL;
}
static Error* exprSlice1(Compiler* self) {
Error* err;
SliceExpr* slice = SliceExpr__new(prev()->line);
slice->start = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)slice); // push onto the stack in advance
if(is_expression(self, false)) { // <start>:<stop>
check(EXPR(self));
slice->stop = Ctx__s_popx(ctx());
// try optional step
if(match(TK_COLON)) { // <start>:<stop>:<step>
check(EXPR(self));
slice->step = Ctx__s_popx(ctx());
}
} else if(match(TK_COLON)) { // <start>::<step>
check(EXPR(self));
slice->step = Ctx__s_popx(ctx());
} // else <start>:
return NULL;
}
static Error* exprSubscr(Compiler* self) {
Error* err;
int line = prev()->line;
check(EXPR_TUPLE_ALLOW_SLICE(self, true));
consume(TK_RBRACKET); // [lhs, rhs]
SubscrExpr* e = SubscrExpr__new(line);
e->rhs = Ctx__s_popx(ctx()); // [lhs]
e->lhs = Ctx__s_popx(ctx()); // []
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
}
////////////////
static Error* consume_type_hints(Compiler* self) {
Error* err;
check(EXPR(self));
Ctx__s_pop(ctx());
return NULL;
}
static Error* consume_type_hints_sv(Compiler* self, c11_sv* out) {
Error* err;
const char* start = curr()->start;
check(EXPR(self));
const char* end = prev()->start + prev()->length;
*out = (c11_sv){start, end - start};
Ctx__s_pop(ctx());
return NULL;
}
static Error* compile_stmt(Compiler* self);
static Error* compile_block_body(Compiler* self) {
Error* err;
consume(TK_COLON);
if(curr()->type != TK_EOL && curr()->type != TK_EOF) {
while(true) {
check(compile_stmt(self));
bool possible = curr()->type != TK_EOL && curr()->type != TK_EOF;
if(prev()->type != TK_SEMICOLON || !possible) break;
}
return NULL;
}
bool consumed = match_newlines();
if(!consumed) return SyntaxError(self, "expected a new line after ':'");
consume(TK_INDENT);
while(curr()->type != TK_DEDENT) {
match_newlines();
check(compile_stmt(self));
match_newlines();
}
consume(TK_DEDENT);
return NULL;
}
static Error* compile_if_stmt(Compiler* self) {
Error* err;
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, prev()->line);
err = compile_block_body(self);
if(err) return err;
if(match(TK_ELIF)) {
int exit_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, prev()->line);
Ctx__patch_jump(ctx(), patch);
check(compile_if_stmt(self));
Ctx__patch_jump(ctx(), exit_patch);
} else if(match(TK_ELSE)) {
int exit_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, prev()->line);
Ctx__patch_jump(ctx(), patch);
check(compile_block_body(self));
Ctx__patch_jump(ctx(), exit_patch);
} else {
Ctx__patch_jump(ctx(), patch);
}
return NULL;
}
static Error* compile_match_case(Compiler* self, c11_vector* patches) {
Error* err;
bool is_case_default = false;
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
consume(TK_COLON);
bool consumed = match_newlines();
if(!consumed) return SyntaxError(self, "expected a new line after ':'");
consume(TK_INDENT);
while(curr()->type != TK_DEDENT) {
match_newlines();
if(match_id_by_str(self, "case")) {
if(is_case_default) return SyntaxError(self, "case _: must be the last one");
is_case_default = match_id_by_str(self, "_");
if(!is_case_default) {
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, prev()->line);
check(EXPR(self)); // expr
Ctx__s_emit_top(ctx());
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_NOT_MATCH, BC_NOARG, prev()->line);
check(compile_block_body(self));
int break_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, prev()->line);
c11_vector__push(int, patches, break_patch);
Ctx__patch_jump(ctx(), patch);
} else {
check(compile_block_body(self));
}
} else {
return SyntaxError(self, "expected 'case', got '%s'", TokenSymbols[curr()->type]);
}
match_newlines();
}
consume(TK_DEDENT);
for(int i = 0; i < patches->length; i++) {
int patch = c11__getitem(int, patches, i);
Ctx__patch_jump(ctx(), patch);
}
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, prev()->line);
return NULL;
}
static Error* compile_while_loop(Compiler* self) {
Error* err;
int block = Ctx__enter_block(ctx(), CodeBlockType_WHILE_LOOP);
int block_start = c11__at(CodeBlock, &ctx()->co->blocks, block)->start;
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, prev()->line);
check(compile_block_body(self));
Ctx__emit_jump(ctx(), block_start, BC_KEEPLINE);
Ctx__patch_jump(ctx(), patch);
Ctx__exit_block(ctx());
// optional else clause
if(match(TK_ELSE)) {
check(compile_block_body(self));
CodeBlock* p_block = c11__at(CodeBlock, &ctx()->co->blocks, block);
p_block->end2 = ctx()->co->codes.length;
}
return NULL;
}
static Error* compile_for_loop(Compiler* self) {
Error* err;
check(EXPR_VARS(self)); // [vars]
consume(TK_IN);
check(EXPR_TUPLE(self)); // [vars, iter]
Ctx__s_emit_top(ctx()); // [vars]
Ctx__emit_(ctx(), OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
int block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP);
int block_start = Ctx__emit_(ctx(), OP_FOR_ITER, block, BC_KEEPLINE);
Expr* vars = Ctx__s_popx(ctx());
bool ok = vtemit_store(vars, ctx());
vtdelete(vars);
if(!ok) {
// this error occurs in `vars` instead of this line, but...nevermind
return SyntaxError(self, "invalid syntax");
}
check(compile_block_body(self));
Ctx__emit_jump(ctx(), block_start, BC_KEEPLINE);
Ctx__exit_block(ctx());
// optional else clause
if(match(TK_ELSE)) {
check(compile_block_body(self));
CodeBlock* p_block = c11__at(CodeBlock, &ctx()->co->blocks, block);
p_block->end2 = ctx()->co->codes.length;
}
return NULL;
}
static Error* compile_yield_from(Compiler* self, int kw_line) {
Error* err;
if(self->contexts.length <= 1) return SyntaxError(self, "'yield from' outside function");
check(EXPR_TUPLE(self));
Ctx__s_emit_top(ctx());
Ctx__emit_(ctx(), OP_GET_ITER, BC_NOARG, kw_line);
int block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP);
int block_start = Ctx__emit_(ctx(), OP_FOR_ITER_YIELD_VALUE, block, kw_line);
Ctx__emit_jump(ctx(), block_start, BC_KEEPLINE);
Ctx__exit_block(ctx());
// StopIteration.value will be pushed onto the stack
return NULL;
}
Error* try_compile_assignment(Compiler* self, bool* is_assign) {
Error* err;
switch(curr()->type) {
case TK_IADD:
case TK_ISUB:
case TK_IMUL:
case TK_IDIV:
case TK_IFLOORDIV:
case TK_IMOD:
case TK_ILSHIFT:
case TK_IRSHIFT:
case TK_IAND:
case TK_IOR:
case TK_IXOR: {
if(Ctx__s_top(ctx())->vt->is_starred)
return SyntaxError(self, "can't use inplace operator with starred expression");
if(ctx()->is_compiling_class)
return SyntaxError(self, "can't use inplace operator in class definition");
advance();
// a[x] += 1; a and x should be evaluated only once
// a.x += 1; a should be evaluated only once
// -1 to remove =; inplace=true
int line = prev()->line;
TokenIndex op = (TokenIndex)(prev()->type - 1);
// [lhs]
check(EXPR_TUPLE(self)); // [lhs, rhs]
if(Ctx__s_top(ctx())->vt->is_starred)
return SyntaxError(self, "can't use starred expression here");
BinaryExpr* e = BinaryExpr__new(line, op, true);
e->rhs = Ctx__s_popx(ctx()); // [lhs]
e->lhs = Ctx__s_popx(ctx()); // []
vtemit_((Expr*)e, ctx());
bool ok = vtemit_istore(e->lhs, ctx());
vtdelete((Expr*)e);
if(!ok) return SyntaxError(self, "invalid syntax");
*is_assign = true;
return NULL;
}
case TK_ASSIGN: {
consume(TK_ASSIGN);
int n = 0; // assignment count
if(match(TK_YIELD_FROM)) {
check(compile_yield_from(self, prev()->line));
n = 1;
} else {
do {
check(EXPR_TUPLE(self));
n += 1;
} while(match(TK_ASSIGN));
// stack size is n+1
Ctx__s_emit_top(ctx());
for(int j = 1; j < n; j++)
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
}
for(int j = 0; j < n; j++) {
if(Ctx__s_top(ctx())->vt->is_starred)
return SyntaxError(self, "can't use starred expression here");
Expr* e = Ctx__s_top(ctx());
bool ok = vtemit_store(e, ctx());
Ctx__s_pop(ctx());
if(!ok) return SyntaxError(self, "invalid syntax");
}
*is_assign = true;
return NULL;
}
default: *is_assign = false;
}
return NULL;
}
static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index) {
FuncDecl_ decl = FuncDecl__rcnew(self->src, name);
decl->code.start_line = self->i == 0 ? 1 : prev()->line;
decl->nested = name_scope(self) == NAME_LOCAL;
// add_func_decl
Ctx* top_ctx = ctx();
c11_vector__push(FuncDecl_, &top_ctx->co->func_decls, decl);
*out_index = top_ctx->co->func_decls.length - 1;
// push new context
top_ctx = c11_vector__emplace(&self->contexts);
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.length);
return decl;
}
static Error* read_literal(Compiler* self, py_Ref out) {
Error* err;
advance();
const TokenValue* value = &prev()->value;
bool negated = false;
switch(prev()->type) {
case TK_SUB:
consume(TK_NUM);
value = &prev()->value;
negated = true;
case TK_NUM: {
if(value->index == TokenValue_I64) {
py_newint(out, negated ? -value->_i64 : value->_i64);
} else if(value->index == TokenValue_F64) {
py_newfloat(out, negated ? -value->_f64 : value->_f64);
} else {
c11__unreachable();
}
return NULL;
}
case TK_STR: py_newstr(out, value->_str->data); return NULL;
case TK_TRUE: py_newbool(out, true); return NULL;
case TK_FALSE: py_newbool(out, false); return NULL;
case TK_NONE: py_newnone(out); return NULL;
case TK_DOTDOTDOT: py_newellipsis(out); return NULL;
case TK_LPAREN: {
py_TValue cpnts[4];
int count = 0;
while(true) {
if(count == 4)
return SyntaxError(self, "default argument tuple exceeds 4 elements");
check(read_literal(self, &cpnts[count]));
count += 1;
if(curr()->type == TK_RPAREN) break;
consume(TK_COMMA);
if(curr()->type == TK_RPAREN) break;
}
consume(TK_RPAREN);
py_Ref p = py_newtuple(out, count);
for(int i = 0; i < count; i++) {
p[i] = cpnts[i];
}
return NULL;
}
default: {
return SyntaxError(self, "expected a literal, got '%s'", TokenSymbols[prev()->type]);
}
}
}
static Error* _compile_f_args(Compiler* self, FuncDecl* decl, bool is_lambda) {
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
Error* err;
do {
// allow trailing comma
if(!is_lambda && curr()->type == TK_RPAREN) break;
if(state >= 3) return SyntaxError(self, "**kwargs should be the last argument");
if(match(TK_MUL)) {
if(state < 1)
state = 1;
else
return SyntaxError(self, "*args should be placed before **kwargs");
} else if(match(TK_POW)) {
state = 3;
}
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
// check duplicate argument name
if(FuncDecl__is_duplicated_arg(decl, name)) {
return SyntaxError(self, "duplicate argument name");
}
// eat type hints
if(!is_lambda && match(TK_COLON)) check(consume_type_hints(self));
if(state == 0 && curr()->type == TK_ASSIGN) state = 2;
switch(state) {
case 0: FuncDecl__add_arg(decl, name); break;
case 1:
FuncDecl__add_starred_arg(decl, name);
state += 1;
break;
case 2: {
consume(TK_ASSIGN);
py_TValue value;
check(read_literal(self, &value));
FuncDecl__add_kwarg(decl, name, &value);
} break;
case 3:
FuncDecl__add_starred_kwarg(decl, name);
state += 1;
break;
}
} while(match(TK_COMMA));
return NULL;
}
static Error* consume_pep695_py312(Compiler* self) {
// https://peps.python.org/pep-0695/
Error* err;
if(match(TK_LBRACKET)) {
do {
consume(TK_ID);
if(match(TK_COLON)) check(consume_type_hints(self));
} while(match(TK_COMMA));
consume(TK_RBRACKET);
}
return NULL;
}
static Error* compile_function(Compiler* self, int decorators) {
Error* err;
int def_line = prev()->line;
consume(TK_ID);
c11_sv decl_name_sv = Token__sv(prev());
int decl_index;
FuncDecl_ decl = push_f_context(self, decl_name_sv, &decl_index);
consume_pep695_py312(self);
consume(TK_LPAREN);
if(!match(TK_RPAREN)) {
check(_compile_f_args(self, decl, false));
consume(TK_RPAREN);
}
if(match(TK_ARROW)) check(consume_type_hints(self));
check(compile_block_body(self));
check(pop_context(self));
if(decl->code.codes.length >= 2) {
Bytecode* codes = (Bytecode*)decl->code.codes.data;
if(codes[0].op == OP_LOAD_CONST && codes[1].op == OP_POP_TOP) {
// handle optional docstring
py_TValue* consts = decl->code.consts.data;
py_TValue* c = &consts[codes[0].arg];
if(py_isstr(c)) {
decl->docstring = c11_strdup(py_tostr(c));
codes[0].op = OP_NO_OP;
codes[1].op = OP_NO_OP;
}
}
}
Ctx__emit_(ctx(), OP_LOAD_FUNCTION, decl_index, def_line);
Ctx__s_emit_decorators(ctx(), decorators);
py_Name decl_name = py_namev(decl_name_sv);
if(ctx()->is_compiling_class) {
if(decl_name == __new__ || decl_name == __init__) {
if(decl->args.length == 0) {
return SyntaxError(self,
"%s() should have at least one positional argument",
py_name2str(decl_name));
}
}
Ctx__emit_(ctx(), OP_STORE_CLASS_ATTR, Ctx__add_name(ctx(), decl_name), def_line);
} else {
NameExpr* e = NameExpr__new(def_line, decl_name, name_scope(self));
vtemit_store((Expr*)e, ctx());
vtdelete((Expr*)e);
}
return NULL;
}
static Error* compile_class(Compiler* self, int decorators) {
Error* err;
if(ctx()->level > 1) return SyntaxError(self, "class definition not allowed here");
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
bool has_base = false;
consume_pep695_py312(self);
if(match(TK_LPAREN)) {
if(is_expression(self, false)) {
check(EXPR(self));
has_base = true; // [base]
}
consume(TK_RPAREN);
}
if(!has_base) {
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
} else {
Ctx__s_emit_top(ctx()); // []
}
Ctx__emit_(ctx(), OP_BEGIN_CLASS, Ctx__add_name(ctx(), name), BC_KEEPLINE);
c11__foreach(Ctx, &self->contexts, it) {
if(it->is_compiling_class) return SyntaxError(self, "nested class is not allowed");
}
ctx()->is_compiling_class = true;
check(compile_block_body(self));
ctx()->is_compiling_class = false;
Ctx__s_emit_decorators(ctx(), decorators);
Ctx__emit_(ctx(), OP_END_CLASS, Ctx__add_name(ctx(), name), BC_KEEPLINE);
return NULL;
}
static Error* compile_decorated(Compiler* self) {
Error* err;
int count = 0;
do {
check(EXPR(self));
count += 1;
if(!match_newlines()) return SyntaxError(self, "expected a newline after '@'");
} while(match(TK_DECORATOR));
if(match(TK_CLASS)) {
check(compile_class(self, count));
} else {
consume(TK_DEF);
check(compile_function(self, count));
}
return NULL;
}
// import a [as b]
// import a [as b], c [as d]
static Error* compile_normal_import(Compiler* self, c11_sbuf* buf) {
do {
consume(TK_ID);
c11_sv name = Token__sv(prev());
c11_sbuf__write_sv(buf, name);
bool has_sub_cpnt = false;
while(match(TK_DOT)) {
has_sub_cpnt = true;
consume(TK_ID);
c11_sbuf__write_char(buf, '.');
c11_sbuf__write_sv(buf, Token__sv(prev()));
}
c11_string* path = c11_sbuf__submit(buf);
int path_index = Ctx__add_const_string(ctx(), c11_string__sv(path));
c11_string__delete(path);
NameScope scope = name_scope(self);
Ctx__emit_(ctx(), OP_IMPORT_PATH, path_index, prev()->line);
// [module <path>]
if(!has_sub_cpnt) {
if(match(TK_AS)) {
// import a as x
consume(TK_ID);
name = Token__sv(prev());
} else {
// import a
}
} else {
if(match(TK_AS)) {
// import a.b as x
consume(TK_ID);
name = Token__sv(prev());
} else {
// import a.b
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
int index = Ctx__add_const_string(ctx(), name);
Ctx__emit_(ctx(), OP_IMPORT_PATH, index, BC_KEEPLINE);
}
}
Ctx__emit_store_name(ctx(), scope, py_namev(name), BC_KEEPLINE);
} while(match(TK_COMMA));
consume_end_stmt();
return NULL;
}
// from a import b [as c], d [as e]
// from a.b import c [as d]
// from . import a [as b]
// from .a import b [as c]
// from ..a import b [as c]
// from .a.b import c [as d]
// from xxx import *
static Error* compile_from_import(Compiler* self, c11_sbuf* buf) {
int dots = 0;
while(true) {
switch(curr()->type) {
case TK_DOT: dots += 1; break;
case TK_DOTDOT: dots += 2; break;
case TK_DOTDOTDOT: dots += 3; break;
default: goto __EAT_DOTS_END;
}
advance();
}
__EAT_DOTS_END:
for(int i = 0; i < dots; i++) {
c11_sbuf__write_char(buf, '.');
}
if(dots > 0) {
// @id is optional if dots > 0
if(match(TK_ID)) {
c11_sbuf__write_sv(buf, Token__sv(prev()));
while(match(TK_DOT)) {
consume(TK_ID);
c11_sbuf__write_char(buf, '.');
c11_sbuf__write_sv(buf, Token__sv(prev()));
}
}
} else {
// @id is required if dots == 0
consume(TK_ID);
c11_sbuf__write_sv(buf, Token__sv(prev()));
while(match(TK_DOT)) {
consume(TK_ID);
c11_sbuf__write_char(buf, '.');
c11_sbuf__write_sv(buf, Token__sv(prev()));
}
}
c11_string* path = c11_sbuf__submit(buf);
Ctx__emit_(ctx(),
OP_IMPORT_PATH,
Ctx__add_const_string(ctx(), c11_string__sv(path)),
prev()->line);
c11_string__delete(path);
consume(TK_IMPORT);
if(match(TK_MUL)) {
if(name_scope(self) != NAME_GLOBAL)
return SyntaxError(self, "from <module> import * can only be used in global scope");
// pop the module and import __all__
Ctx__emit_(ctx(), OP_POP_IMPORT_STAR, BC_NOARG, prev()->line);
consume_end_stmt();
return NULL;
}
bool has_bracket = match(TK_LPAREN);
do {
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
consume(TK_ID);
c11_sv name = Token__sv(prev());
Ctx__emit_(ctx(), OP_LOAD_ATTR, Ctx__add_name(ctx(), py_namev(name)), prev()->line);
if(match(TK_AS)) {
consume(TK_ID);
name = Token__sv(prev());
}
Ctx__emit_store_name(ctx(), name_scope(self), py_namev(name), prev()->line);
} while(match(TK_COMMA));
if(has_bracket) { consume(TK_RPAREN); }
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
consume_end_stmt();
return NULL;
}
static Error* compile_try_except(Compiler* self) {
Error* err;
int patches[8];
int patches_length = 0;
Ctx__enter_block(ctx(), CodeBlockType_TRY);
Ctx__emit_(ctx(), OP_BEGIN_TRY, BC_NOARG, prev()->line);
check(compile_block_body(self));
Ctx__emit_(ctx(), OP_END_TRY, BC_NOARG, BC_KEEPLINE);
// https://docs.python.org/3/reference/compound_stmts.html#finally-clause
/* If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed,
* including any except and else clauses. If an exception occurs in any of the clauses and is
* not handled, the exception is temporarily saved. The finally clause is executed. If there is
* a saved exception it is re-raised at the end of the finally clause. If the finally clause
* raises another exception, the saved exception is set as the context of the new exception. If
* the finally clause executes a return, break or continue statement, the saved exception is
* discarded.
*/
// known issue:
// A return, break, continue in try/except block will make the finally block not executed
bool has_finally = curr()->type == TK_FINALLY;
if(has_finally) return SyntaxError(self, "finally clause is not supported yet");
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
Ctx__exit_block(ctx());
do {
if(patches_length == 8) {
return SyntaxError(self, "maximum number of except clauses reached");
}
py_Name as_name = 0;
consume(TK_EXCEPT);
if(is_expression(self, false)) {
// except <expr>:
check(EXPR(self));
Ctx__s_emit_top(ctx());
Ctx__emit_(ctx(), OP_EXCEPTION_MATCH, BC_NOARG, prev()->line);
if(match(TK_AS)) {
// except <expr> as <name>:
consume(TK_ID);
as_name = py_namev(Token__sv(prev()));
}
} else {
// except:
Ctx__emit_(ctx(), OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
}
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
// on match
Ctx__emit_(ctx(), OP_HANDLE_EXCEPTION, BC_NOARG, BC_KEEPLINE);
if(as_name) {
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
}
Ctx__enter_block(ctx(), CodeBlockType_EXCEPT);
check(compile_block_body(self));
Ctx__exit_block(ctx());
Ctx__emit_(ctx(), OP_END_TRY, BC_NOARG, BC_KEEPLINE);
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
Ctx__patch_jump(ctx(), patch);
} while(curr()->type == TK_EXCEPT);
// no match, re-raise
Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
// match one & handled, jump to the end
for(int i = 0; i < patches_length; i++) {
Ctx__patch_jump(ctx(), patches[i]);
}
if(match(TK_FINALLY)) return SyntaxError(self, "finally clause is not supported yet");
return NULL;
}
static Error* compile_stmt(Compiler* self) {
Error* err;
if(match(TK_CLASS)) {
check(compile_class(self, 0));
return NULL;
}
advance();
int kw_line = prev()->line; // backup line number
switch(prev()->type) {
case TK_BREAK: {
int curr_loop_block = Ctx__prepare_loop_divert(ctx(), kw_line, true);
if(curr_loop_block < 0) return SyntaxError(self, "'break' outside loop");
Ctx__emit_(ctx(), OP_LOOP_BREAK, curr_loop_block, kw_line);
consume_end_stmt();
break;
}
case TK_CONTINUE: {
int curr_loop_block = Ctx__prepare_loop_divert(ctx(), kw_line, false);
if(curr_loop_block < 0) return SyntaxError(self, "'continue' not properly in loop");
Ctx__emit_(ctx(), OP_LOOP_CONTINUE, curr_loop_block, kw_line);
consume_end_stmt();
break;
}
case TK_YIELD:
if(self->contexts.length <= 1) return SyntaxError(self, "'yield' outside function");
if(match_end_stmt(self)) {
Ctx__emit_(ctx(), OP_YIELD_VALUE, 1, kw_line);
} else {
check(EXPR_TUPLE(self));
Ctx__s_emit_top(ctx());
Ctx__emit_(ctx(), OP_YIELD_VALUE, BC_NOARG, kw_line);
consume_end_stmt();
}
break;
case TK_YIELD_FROM:
check(compile_yield_from(self, kw_line));
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, kw_line);
consume_end_stmt();
break;
case TK_RETURN:
if(self->contexts.length <= 1) return SyntaxError(self, "'return' outside function");
if(match_end_stmt(self)) {
Ctx__emit_(ctx(), OP_RETURN_VALUE, 1, kw_line);
} else {
check(EXPR_TUPLE(self));
Ctx__s_emit_top(ctx());
consume_end_stmt();
Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, kw_line);
}
break;
/*************************************************/
case TK_IF: check(compile_if_stmt(self)); break;
case TK_MATCH: {
c11_vector patches;
c11_vector__ctor(&patches, sizeof(int));
check(compile_match_case(self, &patches));
c11_vector__dtor(&patches);
break;
}
case TK_WHILE: check(compile_while_loop(self)); break;
case TK_FOR: check(compile_for_loop(self)); break;
case TK_IMPORT: {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
err = compile_normal_import(self, &buf);
c11_sbuf__dtor(&buf);
if(err) return err;
break;
}
case TK_FROM: {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
err = compile_from_import(self, &buf);
c11_sbuf__dtor(&buf);
if(err) return err;
break;
}
case TK_DEF: check(compile_function(self, 0)); break;
case TK_DECORATOR: check(compile_decorated(self)); break;
case TK_TRY: check(compile_try_except(self)); break;
case TK_PASS: consume_end_stmt(); break;
/*************************************************/
case TK_ASSERT: {
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
int index = Ctx__emit_(ctx(), OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
int has_msg = 0;
if(match(TK_COMMA)) {
check(EXPR(self)); // message
Ctx__s_emit_top(ctx());
has_msg = 1;
}
Ctx__emit_(ctx(), OP_RAISE_ASSERT, has_msg, kw_line);
Ctx__patch_jump(ctx(), index);
consume_end_stmt();
break;
}
case TK_GLOBAL:
do {
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
c11_smallmap_n2d__set(&ctx()->global_names, name, 0);
} while(match(TK_COMMA));
consume_end_stmt();
break;
case TK_RAISE: {
if(is_expression(self, false)) {
check(EXPR(self));
Ctx__s_emit_top(ctx());
Ctx__emit_(ctx(), OP_RAISE, BC_NOARG, kw_line);
} else {
int iblock = ctx()->curr_iblock;
CodeBlock* blocks = (CodeBlock*)ctx()->co->blocks.data;
if(blocks[iblock].type != CodeBlockType_EXCEPT) {
return SyntaxError(self,
"raise without exception is only allowed in except block");
}
Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, kw_line);
}
consume_end_stmt();
} break;
case TK_DEL: {
check(EXPR_TUPLE(self));
Expr* e = Ctx__s_top(ctx());
if(!vtemit_del(e, ctx())) return SyntaxError(self, "invalid syntax");
Ctx__s_pop(ctx());
consume_end_stmt();
} break;
case TK_WITH: {
check(EXPR(self)); // [ <expr> ]
Ctx__s_emit_top(ctx());
Ctx__enter_block(ctx(), CodeBlockType_WITH);
NameExpr* as_name = NULL;
if(match(TK_AS)) {
consume(TK_ID);
py_Name name = py_namev(Token__sv(prev()));
as_name = NameExpr__new(prev()->line, name, name_scope(self));
}
Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev()->line);
// [ <expr> <expr>.__enter__() ]
if(as_name) {
bool ok = vtemit_store((Expr*)as_name, ctx());
vtdelete((Expr*)as_name);
if(!ok) return SyntaxError(self, "invalid syntax");
} else {
// discard `__enter__()`'s return value
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
}
check(compile_block_body(self));
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
Ctx__exit_block(ctx());
} break;
/*************************************************/
// handle dangling expression or assignment
default: {
// do revert since we have pre-called advance() at the beginning
--self->i;
check(EXPR_TUPLE(self));
bool is_typed_name = false; // e.g. x: int
// eat variable's type hint if it is a single name
const ExprVt* top_vt = Ctx__s_top(ctx())->vt;
if(top_vt->is_name || top_vt->is_attrib) {
if(match(TK_COLON)) {
c11_sv type_hint;
check(consume_type_hints_sv(self, &type_hint));
is_typed_name = true;
if(ctx()->is_compiling_class && top_vt->is_name) {
NameExpr* ne = (NameExpr*)Ctx__s_top(ctx());
int index = Ctx__add_const_string(ctx(), type_hint);
Ctx__emit_(ctx(), OP_LOAD_CONST, index, BC_KEEPLINE);
Ctx__emit_(ctx(),
OP_ADD_CLASS_ANNOTATION,
Ctx__add_name(ctx(), ne->name),
BC_KEEPLINE);
}
}
}
bool is_assign = false;
check(try_compile_assignment(self, &is_assign));
if(!is_assign) {
if(Ctx__s_size(ctx()) > 0 && Ctx__s_top(ctx())->vt->is_starred) {
return SyntaxError(self, "can't use starred expression here");
}
if(!is_typed_name) {
Ctx__s_emit_top(ctx());
if((mode() == SINGLE_MODE) && name_scope(self) == NAME_GLOBAL) {
Ctx__emit_(ctx(), OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
} else {
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
}
} else {
Ctx__s_pop(ctx());
}
}
consume_end_stmt();
break;
}
}
return NULL;
}
/////////////////////////////////////////////////////////////////
Error* Compiler__compile(Compiler* self, CodeObject* out) {
// make sure it is the first time to compile
assert(self->i == 0);
// make sure the first token is @sof
assert(tk(0)->type == TK_SOF);
push_global_context(self, out);
advance(); // skip @sof, so prev() is always valid
match_newlines(); // skip possible leading '\n'
Error* err;
if(mode() == EVAL_MODE) {
check(EXPR_TUPLE(self));
Ctx__s_emit_top(ctx());
consume(TK_EOF);
Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
check(pop_context(self));
return NULL;
}
while(!match(TK_EOF)) {
check(compile_stmt(self));
match_newlines();
}
check(pop_context(self));
return NULL;
}
Error* pk_compile(SourceData_ src, CodeObject* out) {
Token* tokens;
int tokens_length;
Error* err = Lexer__process(src, &tokens, &tokens_length);
if(err) return err;
#if 0
Token* data = (Token*)tokens.data;
printf("%s\n", src->filename->data);
for(int i = 0; i < tokens.length; i++) {
Token* t = data + i;
c11_string* tmp = c11_string__new2(t->start, t->length);
if(t->value.index == TokenValue_STR) {
const char* value_str = t->value._str->data;
printf("[%d] %s: %s (value._str=%s)\n",
t->line,
TokenSymbols[t->type],
tmp->data,
value_str);
} else {
printf("[%d] %s: %s\n", t->line, TokenSymbols[t->type], tmp->data);
}
c11_string__delete(tmp);
}
#endif
Compiler compiler;
Compiler__ctor(&compiler, src, tokens, tokens_length);
CodeObject__ctor(out, src, c11_string__sv(src->filename));
err = Compiler__compile(&compiler, out);
if(err) {
// dispose the code object if error occurs
CodeObject__dtor(out);
}
Compiler__dtor(&compiler);
return err;
}
// clang-format off
const static PrattRule rules[TK__COUNT__] = {
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
[TK_DOT] = { NULL, exprAttrib, PREC_PRIMARY },
[TK_LPAREN] = { exprGroup, exprCall, PREC_PRIMARY },
[TK_LBRACKET] = { exprList, exprSubscr, PREC_PRIMARY },
[TK_MOD] = { NULL, exprBinaryOp, PREC_FACTOR },
[TK_ADD] = { NULL, exprBinaryOp, PREC_TERM },
[TK_SUB] = { exprUnaryOp, exprBinaryOp, PREC_TERM },
[TK_MUL] = { exprUnaryOp, exprBinaryOp, PREC_FACTOR },
[TK_INVERT] = { exprUnaryOp, NULL, PREC_UNARY },
[TK_DIV] = { NULL, exprBinaryOp, PREC_FACTOR },
[TK_FLOORDIV] = { NULL, exprBinaryOp, PREC_FACTOR },
[TK_POW] = { exprUnaryOp, exprBinaryOp, PREC_EXPONENT },
[TK_GT] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_LT] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_EQ] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_NE] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_GE] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_LE] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_IN] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_IS] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_LSHIFT] = { NULL, exprBinaryOp, PREC_BITWISE_SHIFT },
[TK_RSHIFT] = { NULL, exprBinaryOp, PREC_BITWISE_SHIFT },
[TK_AND] = { NULL, exprBinaryOp, PREC_BITWISE_AND },
[TK_OR] = { NULL, exprBinaryOp, PREC_BITWISE_OR },
[TK_XOR] = { NULL, exprBinaryOp, PREC_BITWISE_XOR },
[TK_DECORATOR] = { NULL, exprBinaryOp, PREC_FACTOR },
[TK_IF] = { NULL, exprTernary, PREC_TERNARY },
[TK_NOT_IN] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_IS_NOT] = { NULL, exprBinaryOp, PREC_COMPARISION },
[TK_AND_KW ] = { NULL, exprAnd, PREC_LOGICAL_AND },
[TK_OR_KW] = { NULL, exprOr, PREC_LOGICAL_OR },
[TK_NOT_KW] = { exprNot, NULL, PREC_LOGICAL_NOT },
[TK_TRUE] = { exprLiteral0 },
[TK_FALSE] = { exprLiteral0 },
[TK_NONE] = { exprLiteral0 },
[TK_DOTDOTDOT] = { exprLiteral0 },
[TK_LAMBDA] = { exprLambda, },
[TK_ID] = { exprName, },
[TK_NUM] = { exprLiteral, },
[TK_STR] = { exprLiteral, },
[TK_FSTR_BEGIN] = { exprFString, },
[TK_IMAG] = { exprImag, },
[TK_BYTES] = { exprBytes, },
[TK_LBRACE] = { exprMap },
[TK_COLON] = { exprSlice0, exprSlice1, PREC_PRIMARY }
};
// clang-format on
#undef vtcall
#undef vtemit_
#undef vtemit_del
#undef vtemit_store
#undef vtemit_inplace
#undef vtemit_istore
#undef vtdelete
#undef EXPR_COMMON_HEADER
#undef is_compare_expr
#undef tk
#undef prev
#undef curr
#undef next
#undef advance
#undef mode
#undef ctx
#undef match_newlines
#undef consume
#undef consume_end_stmt
#undef check
#undef match
// src/compiler\lexer.c
#include <ctype.h>
#define is_raw_string_used(t) ((t) == TK_ID)
typedef struct Lexer {
SourceData_ src;
const char* token_start;
const char* curr_char;
int current_line;
int brackets_level;
c11_vector /*T=Token*/ nexts;
c11_vector /*T=int*/ indents;
} Lexer;
const static TokenValue EmptyTokenValue;
static Error* lex_one_token(Lexer* self, bool* eof, bool is_fstring);
static void Lexer__ctor(Lexer* self, SourceData_ src) {
PK_INCREF(src);
self->src = src;
self->curr_char = self->token_start = src->source->data;
self->current_line = 1;
self->brackets_level = 0;
c11_vector__ctor(&self->nexts, sizeof(Token));
c11_vector__ctor(&self->indents, sizeof(int));
}
static void Lexer__dtor(Lexer* self) {
PK_DECREF(self->src);
c11_vector__dtor(&self->nexts);
c11_vector__dtor(&self->indents);
}
static char eatchar(Lexer* self) {
char c = *self->curr_char;
assert(c != '\n'); // eatchar() cannot consume a newline
self->curr_char++;
return c;
}
static char eatchar_include_newline(Lexer* self) {
char c = *self->curr_char;
self->curr_char++;
if(c == '\n') {
self->current_line++;
c11_vector__push(const char*, &self->src->line_starts, self->curr_char);
}
return c;
}
static int eat_spaces(Lexer* self) {
int count = 0;
while(true) {
switch(*self->curr_char) {
case ' ': count += 1; break;
case '\t': count += 4; break;
default: return count;
}
eatchar(self);
}
}
static bool matchchar(Lexer* self, char c) {
if(*self->curr_char != c) return false;
eatchar_include_newline(self);
return true;
}
static bool match_n_chars(Lexer* self, int n, char c0) {
const char* c = self->curr_char;
for(int i = 0; i < n; i++) {
if(*c == '\0') return false;
if(*c != c0) return false;
c++;
}
for(int i = 0; i < n; i++)
eatchar_include_newline(self);
return true;
}
static void skip_line_comment(Lexer* self) {
while(*self->curr_char) {
if(*self->curr_char == '\n') return;
eatchar(self);
}
}
static void add_token_with_value(Lexer* self, TokenIndex type, TokenValue value) {
switch(type) {
case TK_LBRACE:
case TK_LBRACKET:
case TK_LPAREN: self->brackets_level++; break;
case TK_RPAREN:
case TK_RBRACKET:
case TK_RBRACE: self->brackets_level--; break;
default: break;
}
Token token = {type,
self->token_start,
(int)(self->curr_char - self->token_start),
self->current_line - ((type == TK_EOL) ? 1 : 0),
self->brackets_level,
value};
// handle "not in", "is not", "yield from"
if(self->nexts.length > 0) {
Token* back = &c11_vector__back(Token, &self->nexts);
if(back->type == TK_NOT_KW && type == TK_IN) {
back->type = TK_NOT_IN;
return;
}
if(back->type == TK_IS && type == TK_NOT_KW) {
back->type = TK_IS_NOT;
return;
}
if(back->type == TK_YIELD && type == TK_FROM) {
back->type = TK_YIELD_FROM;
return;
}
c11_vector__push(Token, &self->nexts, token);
}
}
static void add_token(Lexer* self, TokenIndex type) {
add_token_with_value(self, type, EmptyTokenValue);
}
static void add_token_2(Lexer* self, char c, TokenIndex one, TokenIndex two) {
if(matchchar(self, c))
add_token(self, two);
else
add_token(self, one);
}
static bool eat_indentation(Lexer* self) {
if(self->brackets_level > 0) return true;
int spaces = eat_spaces(self);
if(*self->curr_char == '#') skip_line_comment(self);
if(*self->curr_char == '\0' || *self->curr_char == '\n') { return true; }
// https://docs.python.org/3/reference/lexical_analysis.html#indentation
int indents_back = c11_vector__back(int, &self->indents);
if(spaces > indents_back) {
c11_vector__push(int, &self->indents, spaces);
Token t = {TK_INDENT,
self->token_start,
0,
self->current_line,
self->brackets_level,
EmptyTokenValue};
c11_vector__push(Token, &self->nexts, t);
} else if(spaces < indents_back) {
do {
c11_vector__pop(&self->indents);
Token t = {TK_DEDENT,
self->token_start,
0,
self->current_line,
self->brackets_level,
EmptyTokenValue};
c11_vector__push(Token, &self->nexts, t);
indents_back = c11_vector__back(int, &self->indents);
} while(spaces < indents_back);
if(spaces != indents_back) { return false; }
}
return true;
}
static bool is_possible_number_char(char c) {
switch(c) {
// clang-format off
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case '.': case 'x': case 'o': case 'j':
return true;
default: return false;
// clang-format on
}
}
/******************************/
static Error* LexerError(Lexer* self, const char* fmt, ...) {
Error* err = PK_MALLOC(sizeof(Error));
err->src = self->src;
PK_INCREF(self->src);
err->lineno = self->current_line;
if(*self->curr_char == '\n') { err->lineno--; }
va_list args;
va_start(args, fmt);
vsnprintf(err->msg, sizeof(err->msg), fmt, args);
va_end(args);
return err;
}
static Error* eat_name(Lexer* self) {
self->curr_char--;
while(true) {
unsigned char c = *self->curr_char;
int u8bytes = c11__u8_header(c, true);
if(u8bytes == 0) return LexerError(self, "invalid char: %c", c);
if(u8bytes == 1) {
if(isalnum(c) || c == '_') {
self->curr_char++;
continue;
} else {
break;
}
}
int value = c11__u8_value(u8bytes, self->curr_char);
if(c11__is_unicode_Lo_char(value)) {
self->curr_char += u8bytes;
} else {
break;
}
}
int length = (int)(self->curr_char - self->token_start);
if(length == 0) return LexerError(self, "@id contains invalid char");
c11_sv name = {self->token_start, length};
const char** KW_BEGIN = TokenSymbols + TK_FALSE;
int KW_COUNT = TK__COUNT__ - TK_FALSE;
#define less(a, b) (c11_sv__cmp2(b, a) > 0)
int out;
c11__lower_bound(const char*, KW_BEGIN, KW_COUNT, name, less, &out);
#undef less
if(out != KW_COUNT && c11__sveq2(name, KW_BEGIN[out])) {
add_token(self, (TokenIndex)(out + TK_FALSE));
} else {
add_token(self, TK_ID);
}
return NULL;
}
enum StringType { NORMAL_STRING, RAW_STRING, F_STRING, NORMAL_BYTES };
static Error* _eat_string(Lexer* self, c11_sbuf* buff, char quote, enum StringType type) {
bool is_raw = type == RAW_STRING;
bool is_fstring = type == F_STRING;
if(is_fstring) { add_token(self, TK_FSTR_BEGIN); }
// previous char is quote
bool quote3 = match_n_chars(self, 2, quote);
while(true) {
char c = eatchar_include_newline(self);
if(c == quote) {
if(quote3 && !match_n_chars(self, 2, quote)) {
c11_sbuf__write_char(buff, c);
continue;
}
// end of string
break;
}
if(c == '\0') { return LexerError(self, "EOL while scanning string literal"); }
if(c == '\n') {
if(!quote3)
return LexerError(self, "EOL while scanning string literal");
else {
c11_sbuf__write_char(buff, c);
continue;
}
}
if(!is_raw && c == '\\') {
switch(eatchar_include_newline(self)) {
// For the list of available escape sequences see
// https://docs.python.org/3/reference/lexical_analysis.html#escape-sequences
case '"': c11_sbuf__write_char(buff, '"'); break;
case '\'': c11_sbuf__write_char(buff, '\''); break;
case '\\': c11_sbuf__write_char(buff, '\\'); break;
case 'n': c11_sbuf__write_char(buff, '\n'); break;
case 'r': c11_sbuf__write_char(buff, '\r'); break;
case 't': c11_sbuf__write_char(buff, '\t'); break;
case 'a': c11_sbuf__write_char(buff, '\a'); break;
case 'b': c11_sbuf__write_char(buff, '\b'); break;
case 'f': c11_sbuf__write_char(buff, '\f'); break;
case 'v': c11_sbuf__write_char(buff, '\v'); break;
// Special case for the often used \0 while we don't have full support for octal literals.
case '0': c11_sbuf__write_char(buff, '\0'); break;
case 'x': {
char hex[3] = {eatchar(self), eatchar(self), '\0'};
int code;
if(sscanf(hex, "%x", &code) != 1 || code > 0xFF) {
return LexerError(self, "invalid hex escape");
}
if(type == NORMAL_BYTES) {
// Bytes literals: write raw byte
c11_sbuf__write_char(buff, (char)code);
} else {
// Regular strings: encode as UTF-8
if(code <= 0x7F) {
c11_sbuf__write_char(buff, (char)code);
} else {
// Encode as 2-byte UTF-8 for code points 0x80-0xFF
c11_sbuf__write_char(buff, 0xC0 | (code >> 6)); // Leading byte
c11_sbuf__write_char(buff, 0x80 | (code & 0x3F)); // Continuation byte
}
}
} break;
default: return LexerError(self, "invalid escape char");
}
} else {
if(is_fstring) {
if(c == '{') {
if(matchchar(self, '{')) {
// '{{' -> '{'
c11_sbuf__write_char(buff, '{');
} else {
// submit previous string
c11_string* res = c11_sbuf__submit(buff);
if(res->size > 0) {
TokenValue value = {TokenValue_STR, ._str = res};
add_token_with_value(self, TK_FSTR_CPNT, value);
} else {
c11_string__delete(res);
}
c11_sbuf__ctor(buff); // re-init buffer
// submit {expr} tokens
bool eof = false;
int token_count = self->nexts.length;
while(!eof) {
Error* err = lex_one_token(self, &eof, true);
if(err) return err;
}
if(self->nexts.length == token_count) {
// f'{}' is not allowed
return LexerError(self, "f-string: empty expression not allowed");
}
}
} else if(c == '}') {
if(matchchar(self, '}')) {
// '}}' -> '}'
c11_sbuf__write_char(buff, '}');
} else {
return LexerError(self, "f-string: single '}' is not allowed");
}
} else {
c11_sbuf__write_char(buff, c);
}
} else {
c11_sbuf__write_char(buff, c);
}
}
}
c11_string* res = c11_sbuf__submit(buff);
TokenValue value = {TokenValue_STR, ._str = res};
if(is_fstring) {
if(res->size > 0) {
add_token_with_value(self, TK_FSTR_CPNT, value);
} else {
c11_string__delete(res);
}
add_token(self, TK_FSTR_END);
return NULL;
}
if(type == NORMAL_BYTES) {
add_token_with_value(self, TK_BYTES, value);
} else {
add_token_with_value(self, TK_STR, value);
}
return NULL;
}
static Error* eat_string(Lexer* self, char quote, enum StringType type) {
c11_sbuf buff;
c11_sbuf__ctor(&buff);
Error* err = _eat_string(self, &buff, quote, type);
c11_sbuf__dtor(&buff);
return err;
}
static Error* eat_number(Lexer* self) {
const char* i = self->token_start;
while(is_possible_number_char(*i))
i++;
bool is_scientific_notation = false;
if(*(i - 1) == 'e' && (*i == '+' || *i == '-')) {
i++;
while(isdigit(*i) || *i == 'j')
i++;
is_scientific_notation = true;
}
c11_sv text = {self->token_start, i - self->token_start};
self->curr_char = i;
if(text.data[0] != '.' && !is_scientific_notation) {
// try integer
TokenValue value = {.index = TokenValue_I64};
switch(c11__parse_uint(text, &value._i64, -1)) {
case IntParsing_SUCCESS: add_token_with_value(self, TK_NUM, value); return NULL;
case IntParsing_OVERFLOW: return LexerError(self, "int literal is too large");
case IntParsing_FAILURE: break; // do nothing
}
}
// try float
double float_out;
char* p_end;
float_out = strtod(text.data, &p_end);
if(p_end == text.data + text.size) {
TokenValue value = {.index = TokenValue_F64, ._f64 = float_out};
add_token_with_value(self, TK_NUM, value);
return NULL;
}
if(i[-1] == 'j' && p_end == text.data + text.size - 1) {
TokenValue value = {.index = TokenValue_F64, ._f64 = float_out};
add_token_with_value(self, TK_IMAG, value);
return NULL;
}
return LexerError(self, "invalid number literal");
}
static Error* eat_fstring_spec(Lexer* self, bool* eof) {
while(true) {
char c = eatchar_include_newline(self);
if(c == '\n' || c == '\0') {
return LexerError(self, "EOL while scanning f-string format spec");
}
if(c == '}') {
add_token(self, TK_FSTR_SPEC);
*eof = true;
break;
}
}
return NULL;
}
static Error* lex_one_token(Lexer* self, bool* eof, bool is_fstring) {
*eof = false;
while(*self->curr_char) {
self->token_start = self->curr_char;
char c = eatchar_include_newline(self);
switch(c) {
case '\'':
case '"': {
Error* err = eat_string(self, c, NORMAL_STRING);
if(err) return err;
return NULL;
}
case '#': skip_line_comment(self); break;
case '~': add_token(self, TK_INVERT); return NULL;
case '{': add_token(self, TK_LBRACE); return NULL;
case '}': {
if(is_fstring) {
*eof = true;
return NULL;
}
add_token(self, TK_RBRACE);
return NULL;
}
case ',': add_token(self, TK_COMMA); return NULL;
case ':': {
if(is_fstring) {
// BUG: f"{stack[2:]}"
return eat_fstring_spec(self, eof);
}
add_token(self, TK_COLON);
return NULL;
}
case ';': add_token(self, TK_SEMICOLON); return NULL;
case '(': add_token(self, TK_LPAREN); return NULL;
case ')': add_token(self, TK_RPAREN); return NULL;
case '[': add_token(self, TK_LBRACKET); return NULL;
case ']': add_token(self, TK_RBRACKET); return NULL;
case '@': add_token(self, TK_DECORATOR); return NULL;
case '\\': {
// line continuation character
char c = eatchar_include_newline(self);
if(c != '\n') {
return LexerError(self, "expected newline after line continuation character");
}
eat_spaces(self);
return NULL;
}
case '%': add_token_2(self, '=', TK_MOD, TK_IMOD); return NULL;
case '&': add_token_2(self, '=', TK_AND, TK_IAND); return NULL;
case '|': add_token_2(self, '=', TK_OR, TK_IOR); return NULL;
case '^': add_token_2(self, '=', TK_XOR, TK_IXOR); return NULL;
case '.': {
if(matchchar(self, '.')) {
if(matchchar(self, '.')) {
add_token(self, TK_DOTDOTDOT);
} else {
add_token(self, TK_DOTDOT);
}
} else {
char next_char = *self->curr_char;
if(next_char >= '0' && next_char <= '9') {
Error* err = eat_number(self);
if(err) return err;
} else {
add_token(self, TK_DOT);
}
}
return NULL;
}
case '=': add_token_2(self, '=', TK_ASSIGN, TK_EQ); return NULL;
case '+': add_token_2(self, '=', TK_ADD, TK_IADD); return NULL;
case '>': {
if(matchchar(self, '='))
add_token(self, TK_GE);
else if(matchchar(self, '>'))
add_token_2(self, '=', TK_RSHIFT, TK_IRSHIFT);
else
add_token(self, TK_GT);
return NULL;
}
case '<': {
if(matchchar(self, '='))
add_token(self, TK_LE);
else if(matchchar(self, '<'))
add_token_2(self, '=', TK_LSHIFT, TK_ILSHIFT);
else
add_token(self, TK_LT);
return NULL;
}
case '-': {
if(matchchar(self, '='))
add_token(self, TK_ISUB);
else if(matchchar(self, '>'))
add_token(self, TK_ARROW);
else
add_token(self, TK_SUB);
return NULL;
}
case '!':
if(is_fstring) {
if(matchchar(self, 'r')) { return eat_fstring_spec(self, eof); }
}
if(matchchar(self, '=')) {
add_token(self, TK_NE);
return NULL;
} else {
return LexerError(self, "expected '=' after '!'");
}
case '*':
if(matchchar(self, '*')) {
add_token(self, TK_POW); // '**'
} else {
add_token_2(self, '=', TK_MUL, TK_IMUL);
}
return NULL;
case '/':
if(matchchar(self, '/')) {
add_token_2(self, '=', TK_FLOORDIV, TK_IFLOORDIV);
} else {
add_token_2(self, '=', TK_DIV, TK_IDIV);
}
return NULL;
case ' ':
case '\t': eat_spaces(self); break;
case '\n': {
if(self->brackets_level > 0) return NULL;
add_token(self, TK_EOL);
if(!eat_indentation(self)) {
return LexerError(self, "unindent does not match any outer indentation level");
}
return NULL;
}
default: {
if(c == 'f') {
if(matchchar(self, '\'')) return eat_string(self, '\'', F_STRING);
if(matchchar(self, '"')) return eat_string(self, '"', F_STRING);
} else if(c == 'r') {
if(matchchar(self, '\'')) return eat_string(self, '\'', RAW_STRING);
if(matchchar(self, '"')) return eat_string(self, '"', RAW_STRING);
} else if(c == 'b') {
if(matchchar(self, '\'')) return eat_string(self, '\'', NORMAL_BYTES);
if(matchchar(self, '"')) return eat_string(self, '"', NORMAL_BYTES);
}
if(c >= '0' && c <= '9') return eat_number(self);
return eat_name(self);
}
}
}
if(is_fstring) return LexerError(self, "unterminated f-string expression");
self->token_start = self->curr_char;
while(self->indents.length > 1) {
c11_vector__pop(&self->indents);
add_token(self, TK_DEDENT);
return NULL;
}
add_token(self, TK_EOF);
*eof = true;
return NULL;
}
Error* Lexer__process(SourceData_ src, Token** out_tokens, int* out_length) {
Lexer lexer;
Lexer__ctor(&lexer, src);
// push initial tokens
Token sof =
{TK_SOF, lexer.token_start, 0, lexer.current_line, lexer.brackets_level, EmptyTokenValue};
c11_vector__push(Token, &lexer.nexts, sof);
c11_vector__push(int, &lexer.indents, 0);
bool eof = false;
while(!eof) {
void* err = lex_one_token(&lexer, &eof, false);
if(err) {
Lexer__dtor(&lexer);
return err;
}
}
// set out_tokens
*out_tokens = c11_vector__submit(&lexer.nexts, out_length);
Lexer__dtor(&lexer);
return NULL;
}
const char* TokenSymbols[] = {
"@eof",
"@eol",
"@sof",
"@id",
"@num",
"@str",
"@fstr-begin", // TK_FSTR_BEGIN
"@fstr-cpnt", // TK_FSTR_CPNT
"@fstr-spec", // TK_FSTR_SPEC
"@fstr-end", // TK_FSTR_END
"@bytes",
"@imag",
"@indent",
"@dedent",
// These 3 are compound keywords which are generated on the fly
"is not",
"not in",
"yield from",
/*****************************************/
"+",
"+=",
"-",
"-=", // (INPLACE_OP - 1) can get '=' removed
"*",
"*=",
"/",
"/=",
"//",
"//=",
"%",
"%=",
"&",
"&=",
"|",
"|=",
"^",
"^=",
"<<",
"<<=",
">>",
">>=",
/*****************************************/
"(",
")",
"[",
"]",
"{",
"}",
".",
"..",
"...",
",",
":",
";",
"**",
"->",
"#",
"@",
">",
"<",
"=",
"==",
"!=",
">=",
"<=",
"~",
/** KW_BEGIN **/
// NOTE: These keywords should be sorted in ascending order!!
"False",
"None",
"True",
"and",
"as",
"assert",
"break",
"class",
"continue",
"def",
"del",
"elif",
"else",
"except",
"finally",
"for",
"from",
"global",
"if",
"import",
"in",
"is",
"lambda",
"match",
"not",
"or",
"pass",
"raise",
"return",
"try",
"while",
"with",
"yield",
};
#undef is_raw_string_used
// src/debugger\core.c
#include <ctype.h>
#if PK_ENABLE_OS
typedef struct c11_debugger_breakpoint {
const char* sourcename;
int lineno;
} c11_debugger_breakpoint;
typedef struct c11_debugger_scope_index {
int locals_ref;
int globals_ref;
} c11_debugger_scope_index;
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
#define K int
#define V c11_debugger_scope_index
#define NAME c11_smallmap_d2index
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
#undef SMALLMAP_T__HEADER
static struct c11_debugger {
py_Frame* current_frame;
const char* current_filename;
const char* current_excname;
const char* current_excmessage;
enum py_TraceEvent current_event;
int curr_stack_depth;
int current_line;
int pause_allowed_depth;
int step_line;
C11_STEP_MODE step_mode;
bool keep_suspend;
bool isexceptionmode;
c11_vector* exception_stacktrace;
c11_vector breakpoints;
c11_vector py_frames;
c11_smallmap_d2index scopes_query_cache;
#define python_vars py_sysr0()
} debugger;
inline static void init_structures() {
c11_vector__ctor(&debugger.breakpoints, sizeof(c11_debugger_breakpoint));
c11_vector__ctor(&debugger.py_frames, sizeof(py_Frame*));
c11_smallmap_d2index__ctor(&debugger.scopes_query_cache);
py_newlist(python_vars);
py_newnone(py_list_emplace(python_vars));
}
inline static void clear_structures() {
c11_vector__clear(&debugger.py_frames);
c11_smallmap_d2index__clear(&debugger.scopes_query_cache);
py_list_clear(python_vars);
py_newnone(py_list_emplace(python_vars));
}
inline static py_Ref get_variable(int var_ref) {
assert(var_ref < py_list_len(python_vars) && var_ref > 0);
return py_list_getitem(python_vars, var_ref);
}
const inline static char* format_filepath(const char* path) {
if(strstr(path, "..")) { return NULL; }
if(strstr(path + 1, "./") || strstr(path + 1, ".\\")) { return NULL; }
if(path[0] == '.' && (path[1] == '/' || path[1] == '\\')) { return path + 2; }
return path;
}
void c11_debugger_init() {
debugger.curr_stack_depth = 0;
debugger.current_line = -1;
debugger.pause_allowed_depth = -1;
debugger.step_line = -1;
debugger.keep_suspend = false;
debugger.isexceptionmode = false;
debugger.step_mode = C11_STEP_CONTINUE;
init_structures();
}
C11_DEBUGGER_STATUS c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event) {
debugger.current_frame = frame;
debugger.current_event = event;
const char* source_name = py_Frame_sourceloc(debugger.current_frame, &debugger.current_line);
debugger.current_filename = format_filepath(source_name);
if(debugger.current_filename == NULL) { return C11_DEBUGGER_FILEPATH_ERROR; }
clear_structures();
switch(event) {
case TRACE_EVENT_PUSH: debugger.curr_stack_depth++; break;
case TRACE_EVENT_POP: debugger.curr_stack_depth--; break;
default: break;
}
// if(debugger.curr_stack_depth == 0) return C11_DEBUGGER_EXIT;
return C11_DEBUGGER_SUCCESS;
}
void c11_debugger_exception_on_trace(py_Ref exc) {
BaseException* ud = py_touserdata(exc);
c11_vector* stacktrace = &ud->stacktrace;
const char* name = py_tpname(exc->type);
const char* message = safe_stringify_exception(exc);
debugger.exception_stacktrace = stacktrace;
debugger.isexceptionmode = true;
debugger.current_excname = name;
debugger.current_excmessage = message;
clear_structures();
py_assign(py_list_getitem(python_vars, 0), exc);
py_clearexc(NULL);
}
const char* c11_debugger_excinfo(const char** message) {
*message = debugger.current_excmessage;
return debugger.current_excname;
}
void c11_debugger_set_step_mode(C11_STEP_MODE mode) {
switch(mode) {
case C11_STEP_IN: debugger.pause_allowed_depth = INT32_MAX; break;
case C11_STEP_OVER:
debugger.pause_allowed_depth = debugger.curr_stack_depth;
debugger.step_line = debugger.current_line;
break;
case C11_STEP_OUT: debugger.pause_allowed_depth = debugger.curr_stack_depth - 1; break;
case C11_STEP_CONTINUE: debugger.pause_allowed_depth = -1; break;
default: break;
}
debugger.step_mode = mode;
debugger.keep_suspend = false;
}
int c11_debugger_setbreakpoint(const char* filename, int lineno) {
c11_debugger_breakpoint breakpoint = {.sourcename = c11_strdup(filename), .lineno = lineno};
c11_vector__push(c11_debugger_breakpoint, &debugger.breakpoints, breakpoint);
return debugger.breakpoints.length;
}
int c11_debugger_reset_breakpoints_by_source(const char* sourcesname) {
c11_vector tmp_breakpoints;
c11_vector__ctor(&tmp_breakpoints, sizeof(c11_debugger_breakpoint));
c11__foreach(c11_debugger_breakpoint, &debugger.breakpoints, it) {
if(strcmp(it->sourcename, sourcesname) != 0) {
c11_debugger_breakpoint* dst =
(c11_debugger_breakpoint*)c11_vector__emplace(&tmp_breakpoints);
*dst = *it;
} else {
PK_FREE((void*)it->sourcename);
}
}
c11_vector__swap(&tmp_breakpoints, &debugger.breakpoints);
c11_vector__dtor(&tmp_breakpoints);
return debugger.breakpoints.length;
}
bool c11_debugger_path_equal(const char* path1, const char* path2) {
if(path1 == NULL || path2 == NULL) return false;
while(*path1 && *path2) {
char c1 = (*path1 == '\\') ? '/' : *path1;
char c2 = (*path2 == '\\') ? '/' : *path2;
c1 = (char)tolower((unsigned char)c1);
c2 = (char)tolower((unsigned char)c2);
if(c1 != c2) return false;
path1++;
path2++;
}
return *path1 == *path2;
}
C11_STOP_REASON c11_debugger_should_pause() {
if(debugger.current_event == TRACE_EVENT_POP && !debugger.isexceptionmode)
return C11_DEBUGGER_NOSTOP;
if(py_checkexc() && debugger.isexceptionmode == false)
return C11_DEBUGGER_NOSTOP;
C11_STOP_REASON pause_resaon = C11_DEBUGGER_NOSTOP;
int is_out = debugger.curr_stack_depth <= debugger.pause_allowed_depth;
int is_new_line = debugger.current_line != debugger.step_line;
switch(debugger.step_mode) {
case C11_STEP_IN: pause_resaon = C11_DEBUGGER_STEP; break;
case C11_STEP_OVER:
if(is_new_line && is_out) pause_resaon = C11_DEBUGGER_STEP;
break;
case C11_STEP_OUT:
if(is_out) pause_resaon = C11_DEBUGGER_STEP;
break;
case C11_STEP_CONTINUE:
default: break;
}
if(debugger.step_mode == C11_STEP_CONTINUE) {
c11__foreach(c11_debugger_breakpoint, &debugger.breakpoints, bp) {
if(c11_debugger_path_equal(debugger.current_filename, bp->sourcename) &&
debugger.current_line == bp->lineno) {
pause_resaon = C11_DEBUGGER_BP;
break;
}
}
}
if(debugger.isexceptionmode) pause_resaon = C11_DEBUGGER_EXCEPTION;
if(pause_resaon != C11_DEBUGGER_NOSTOP) { debugger.keep_suspend = true; }
return pause_resaon;
}
int c11_debugger_should_keep_pause(void) { return debugger.keep_suspend; }
inline static c11_sv sv_from_cstr(const char* str) {
c11_sv sv = {.data = str, .size = strlen(str)};
return sv;
}
const inline static char* get_basename(const char* path) {
const char* last_slash = strrchr(path, '/');
#if defined(_WIN32) || defined(_WIN64)
const char* last_backslash = strrchr(path, '\\');
if(!last_slash || (last_backslash && last_backslash > last_slash)) {
last_slash = last_backslash;
}
#endif
return last_slash ? last_slash + 1 : path;
}
void c11_debugger_normal_frames(c11_sbuf* buffer) {
c11_sbuf__write_cstr(buffer, "{\"stackFrames\": [");
int idx = 0;
py_Frame* now_frame = debugger.current_frame;
debugger.py_frames.length = 0;
while(now_frame) {
if(idx > 0) c11_sbuf__write_char(buffer, ',');
int line;
const char* filename = py_Frame_sourceloc(now_frame, &line);
const char* basename = get_basename(filename);
const char* modname = now_frame->co->name->data;
pk_sprintf(
buffer,
"{\"id\": %d, \"name\": %Q, \"line\": %d, \"column\": 1, \"source\": {\"name\": %Q, \"path\": %Q}}",
idx,
sv_from_cstr(modname),
line,
sv_from_cstr(basename),
sv_from_cstr(filename));
c11_vector__push(py_Frame*, &debugger.py_frames, now_frame);
now_frame = now_frame->f_back;
idx++;
}
pk_sprintf(buffer, "], \"totalFrames\": %d}", idx);
}
void c11_debugger_exception_frames(c11_sbuf* buffer) {
c11_sbuf__write_cstr(buffer, "{\"stackFrames\": [");
int idx = 0;
c11__foreach(BaseExceptionFrame, debugger.exception_stacktrace, it) {
if(idx > 0) c11_sbuf__write_char(buffer, ',');
int line = it->lineno;
const char* filename = it->src->filename->data;
const char* basename = get_basename(filename);
const char* modname = it->name == NULL ? basename : it->name->data;
pk_sprintf(
buffer,
"{\"id\": %d, \"name\": %Q, \"line\": %d, \"column\": 1, \"source\": {\"name\": %Q, \"path\": %Q}}",
idx,
sv_from_cstr(modname),
line,
sv_from_cstr(basename),
sv_from_cstr(filename));
idx++;
}
pk_sprintf(buffer, "], \"totalFrames\": %d}", idx);
}
void c11_debugger_frames(c11_sbuf* buffer) {
debugger.isexceptionmode ? c11_debugger_exception_frames(buffer)
: c11_debugger_normal_frames(buffer);
}
inline static c11_debugger_scope_index append_new_scope(int frameid) {
assert(frameid < debugger.py_frames.length);
py_Frame* requested_frame = c11__getitem(py_Frame*, &debugger.py_frames, frameid);
int base_index = py_list_len(python_vars);
py_Ref new_locals = py_list_emplace(python_vars);
py_Frame_newlocals(requested_frame, new_locals);
py_Ref new_globals = py_list_emplace(python_vars);
py_Frame_newglobals(requested_frame, new_globals);
c11_debugger_scope_index result = {.locals_ref = base_index, .globals_ref = base_index + 1};
return result;
}
inline static c11_debugger_scope_index append_new_exception_scope(int frameid) {
assert(frameid < debugger.exception_stacktrace->length);
BaseExceptionFrame* requested_frame =
c11__at(BaseExceptionFrame, debugger.exception_stacktrace, frameid);
int base_index = py_list_len(python_vars);
py_list_append(python_vars, &requested_frame->locals);
py_list_append(python_vars, &requested_frame->globals);
c11_debugger_scope_index result = {.locals_ref = base_index, .globals_ref = base_index + 1};
return result;
}
void c11_debugger_scopes(int frameid, c11_sbuf* buffer) {
// query cache
c11_debugger_scope_index* result =
c11_smallmap_d2index__try_get(&debugger.scopes_query_cache, frameid);
c11_sbuf__write_cstr(buffer, "{\"scopes\":");
const char* scopes_fmt =
"[{\"name\": \"locals\", \"variablesReference\": %d, \"expensive\": false}, "
"{\"name\": \"globals\", \"variablesReference\": %d, \"expensive\": true}]";
if(result != NULL) {
pk_sprintf(buffer, scopes_fmt, result->locals_ref, result->globals_ref);
} else {
c11_debugger_scope_index new_record = debugger.isexceptionmode
? append_new_exception_scope(frameid)
: append_new_scope(frameid);
c11_smallmap_d2index__set(&debugger.scopes_query_cache, frameid, new_record);
pk_sprintf(buffer, scopes_fmt, new_record.locals_ref, new_record.globals_ref);
}
c11_sbuf__write_char(buffer, '}');
}
bool c11_debugger_unfold_var(int var_id, c11_sbuf* buffer) {
py_Ref var = get_variable(var_id);
if(!var) return false;
// 1. extend
const char* expand_code = NULL;
switch(py_typeof(var)) {
case tp_dict:
case tp_namedict: expand_code = "[(k,v) for k,v in _0.items()]"; break;
case tp_list:
case tp_tuple: expand_code = "[(f'[{i}]',v) for i,v in enumerate(_0)]"; break;
default: expand_code = "[(k,v) for k,v in _0.__dict__.items()]"; break;
}
if(!py_smarteval(expand_code, NULL, var)) {
py_printexc();
return false;
}
py_Ref kv_list = py_pushtmp();
py_assign(kv_list, py_retval());
// 2. prepare base_ref
int base_index = py_list_len(python_vars);
py_Ref base_var_ref = py_pushtmp();
py_newint(base_var_ref, base_index);
// 3. construct DAP JSON and extend python_vars
py_Ref dap_obj = py_pushtmp();
py_newdict(dap_obj);
const char* dap_code =
"_2['variables'] = []\n"
"var_ref = _1\n"
"for k, v in _0:\n"
" has_children = isinstance(v, (dict, list, tuple)) or v.__dict__ is not None\n"
" _2['variables'].append({\n"
" 'name': k if type(k) == str else str(k),\n"
" 'value': repr(v) if type(v) == str else str(v),\n"
" 'variablesReference': var_ref if has_children else 0,\n"
" 'type': type(v).__name__\n"
" })\n"
" if has_children: var_ref += 1\n";
if(!py_smartexec(dap_code, NULL, kv_list, base_var_ref, dap_obj)) {
py_printexc();
return false;
}
// 4. extend python_vars
if(!py_smartexec(
"_0.extend([v for k, v in _1 if isinstance(v, (dict, list, tuple)) or v.__dict__ is not None])",
NULL,
python_vars,
kv_list)) {
py_printexc();
return false;
}
// 5. dump & write
if(!py_json_dumps(dap_obj, 0)) {
// printf("dap_obj: %s\n", py_tpname(py_typeof(dap_obj)));
py_printexc();
return false;
}
c11_sbuf__write_cstr(buffer, py_tostr(py_retval()));
// 6. clear
py_pop(); // dap_obj
py_pop(); // base_var_ref
py_pop(); // kv_list
return true;
}
#undef python_vars
#endif // PK_ENABLE_OS
// src/debugger\dap.c
#include <stdbool.h>
#include <stdio.h>
#if PK_ENABLE_OS
#define DAP_COMMAND_LIST(X) \
X(initialize) \
X(setBreakpoints) \
X(attach) \
X(launch) \
X(next) \
X(stepIn) \
X(stepOut) \
X(continue) \
X(stackTrace) \
X(scopes) \
X(variables) \
X(threads) \
X(configurationDone) \
X(ready) \
X(evaluate) \
X(exceptionInfo)
#define DECLARE_HANDLE_FN(name) void c11_dap_handle_##name(py_Ref arguments, c11_sbuf*);
DAP_COMMAND_LIST(DECLARE_HANDLE_FN)
#undef DECLARE_HANDLE_FN
typedef void (*c11_dap_arg_parser_fn)(py_Ref, c11_sbuf*);
typedef struct {
const char* command;
c11_dap_arg_parser_fn parser;
} dap_command_entry;
#define DAP_ENTRY(name) {#name, c11_dap_handle_##name},
static dap_command_entry dap_command_table[] = {
DAP_COMMAND_LIST(DAP_ENTRY){NULL, NULL}
};
#undef DAP_ENTRY
#undef DAP_COMMAND_LIST
static struct c11_dap_server {
int dap_next_seq;
char buffer_data[1024];
char* buffer_begin;
int buffer_length;
c11_socket_handler server;
c11_socket_handler toclient;
bool isconfiguredone;
bool isfirstatttach;
bool isUserCode;
bool isAttached;
bool isclientready;
} server;
void c11_dap_handle_initialize(py_Ref arguments, c11_sbuf* buffer) {
c11_sbuf__write_cstr(buffer,
"\"body\":{"
"\"supportsConfigurationDoneRequest\":true,"
"\"supportsExceptionInfoRequest\":true"
"}");
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_attach(py_Ref arguments, c11_sbuf* buffer) { server.isfirstatttach = true; }
void c11_dap_handle_launch(py_Ref arguments, c11_sbuf* buffer) { server.isfirstatttach = true; }
void c11_dap_handle_ready(py_Ref arguments, c11_sbuf* buffer) { server.isclientready = true; }
void c11_dap_handle_next(py_Ref arguments, c11_sbuf* buffer) {
c11_debugger_set_step_mode(C11_STEP_OVER);
}
void c11_dap_handle_stepIn(py_Ref arguments, c11_sbuf* buffer) {
c11_debugger_set_step_mode(C11_STEP_IN);
}
void c11_dap_handle_stepOut(py_Ref arguments, c11_sbuf* buffer) {
c11_debugger_set_step_mode(C11_STEP_OUT);
}
void c11_dap_handle_continue(py_Ref arguments, c11_sbuf* buffer) {
c11_debugger_set_step_mode(C11_STEP_CONTINUE);
}
void c11_dap_handle_threads(py_Ref arguments, c11_sbuf* buffer) {
c11_sbuf__write_cstr(buffer,
"\"body\":{\"threads\":["
"{\"id\":1,\"name\":\"MainThread\"}"
"]}");
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_configurationDone(py_Ref arguments, c11_sbuf* buffer) {
server.isconfiguredone = true;
}
inline static void c11_dap_build_Breakpoint(int id, int line, c11_sbuf* buffer) {
pk_sprintf(buffer, "{\"id\":%d,\"verified\":true,\"line\":%d}", id, line);
}
void c11_dap_handle_setBreakpoints(py_Ref arguments, c11_sbuf* buffer) {
if(!py_smarteval("_0['source']['path']", NULL, arguments)) {
py_printexc();
return;
}
const char* sourcename = c11_strdup(py_tostr(py_retval()));
if(!py_smarteval("[bp['line'] for bp in _0['breakpoints']]", NULL, arguments)) {
py_printexc();
return;
}
int bp_numbers = c11_debugger_reset_breakpoints_by_source(sourcename);
c11_sbuf__write_cstr(buffer, "\"body\":");
c11_sbuf__write_cstr(buffer, "{\"breakpoints\":[");
for(int i = 0; i < py_list_len(py_retval()); i++) {
if(i != 0) c11_sbuf__write_char(buffer, ',');
int line = py_toint(py_list_getitem(py_retval(), i));
c11_debugger_setbreakpoint(sourcename, line);
c11_dap_build_Breakpoint(i + bp_numbers, line, buffer);
}
c11_sbuf__write_cstr(buffer, "]}");
c11_sbuf__write_char(buffer, ',');
PK_FREE((void*)sourcename);
}
static void c11_dap_build_ExceptionInfo(const char* exc_type, const char* exc_message, c11_sbuf* buffer) {
const char* safe_type = exc_type ? exc_type : "UnknownException";
const char* safe_message = exc_message ? exc_message : "No additional details available";
c11_sv type_sv = {.data = safe_type, .size = strlen(safe_type)};
c11_sbuf combined_buffer;
c11_sbuf__ctor(&combined_buffer);
pk_sprintf(&combined_buffer, "%s: %s", safe_type, safe_message);
c11_string* combined_details = c11_sbuf__submit(&combined_buffer);
pk_sprintf(buffer,
"{\"exceptionId\":%Q,"
"\"description\":%Q,"
"\"breakMode\":\"unhandled\"}",
type_sv,
(c11_sv){.data = combined_details->data, .size = combined_details->size}
);
c11_string__delete(combined_details);
}
void c11_dap_handle_exceptionInfo(py_Ref arguments, c11_sbuf* buffer) {
const char* message;
const char* name = c11_debugger_excinfo(&message);
c11_sbuf__write_cstr(buffer, "\"body\":");
c11_dap_build_ExceptionInfo(name, message, buffer);
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_stackTrace(py_Ref arguments, c11_sbuf* buffer) {
c11_sbuf__write_cstr(buffer, "\"body\":");
c11_debugger_frames(buffer);
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_evaluate(py_Ref arguments, c11_sbuf* buffer) {
int res = py_dict_getitem_by_str(arguments, "expression");
if(res <= 0) {
py_printexc();
c11__abort("[DEBUGGER ERROR] no expression found in evaluate request");
}
// [eval, nil, expression, globals, locals]
// vectorcall would pop the above 5 items
// so we don't need to pop them manually
py_StackRef p0 = py_peek(0);
py_Ref py_eval = py_pushtmp();
py_pushnil();
py_Ref expression = py_pushtmp();
py_assign(expression, py_retval());
py_assign(py_eval, py_getbuiltin(py_name("eval")));
py_newglobals(py_pushtmp());
py_newlocals(py_pushtmp());
bool ok = py_vectorcall(3, 0);
char* result = NULL;
c11_sbuf__write_cstr(buffer, "\"body\":");
if(!ok) {
result = py_formatexc();
py_clearexc(p0);
} else {
py_Ref py_result = py_pushtmp();
py_assign(py_result, py_retval());
py_str(py_result);
py_assign(py_result, py_retval());
result = c11_strdup(py_tostr(py_result));
py_pop();
}
c11_sv result_sv = {.data = result, .size = strlen(result)};
pk_sprintf(buffer, "{\"result\":%Q,\"variablesReference\":0}", result_sv);
PK_FREE((void*)result);
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_scopes(py_Ref arguments, c11_sbuf* buffer) {
int res = py_dict_getitem_by_str(arguments, "frameId");
if(res <= 0) {
if(res == 0) {
c11__abort("[DEBUGGER ERROR] no frameID found in scopes request");
} else {
py_printexc();
c11__abort("[DEBUGGER ERROR] an error occurred while parsing request frameId");
}
return;
}
int frameid = py_toint(py_retval());
c11_sbuf__write_cstr(buffer, "\"body\":");
c11_debugger_scopes(frameid, buffer);
c11_sbuf__write_char(buffer, ',');
}
void c11_dap_handle_variables(py_Ref arguments, c11_sbuf* buffer) {
int res = py_dict_getitem_by_str(arguments, "variablesReference");
if(res <= 0) {
if(res == 0) {
printf("[DEBUGGER ERROR] no frameID found\n");
} else {
py_printexc();
}
return;
}
int variablesReference = py_toint(py_retval());
c11_sbuf__write_cstr(buffer, "\"body\":");
c11_debugger_unfold_var(variablesReference, buffer);
c11_sbuf__write_char(buffer, ',');
}
const char* c11_dap_handle_request(const char* message) {
if(!py_json_loads(message)) {
py_printexc();
c11__abort("[DEBUGGER ERROR] invalid JSON request");
}
py_Ref py_request = py_pushtmp();
py_Ref py_arguments = py_pushtmp();
py_Ref py_command = py_pushtmp();
py_assign(py_request, py_retval());
int res = py_dict_getitem_by_str(py_request, "command");
if(res == -1) {
py_printexc();
c11__abort("[DEBUGGER ERROR] an error occurred while parsing request");
} else if(res == 0) {
c11__abort("[DEBUGGER ERROR] no command found in request");
}
py_assign(py_command, py_retval());
const char* command = py_tostr(py_command);
res = py_dict_getitem_by_str(py_request, "arguments");
if(res == -1) {
py_printexc();
c11__abort("[DEBUGGER ERROR] an error occurred while parsing request arguments");
}
py_assign(py_arguments, py_retval());
res = py_dict_getitem_by_str(py_request, "seq");
if(res == -1) {
py_printexc();
c11__abort("[DEBUGGER ERROR] an error occurred while parsing request sequence number");
}
int request_seq = (res == 1) ? py_toint(py_retval()) : 0;
c11_sbuf response_buffer;
c11_sbuf__ctor(&response_buffer);
pk_sprintf(&response_buffer,
"{\"seq\":%d,\"type\":\"response\",\"request_seq\":%d,\"command\":\"%s\",",
server.dap_next_seq++,
request_seq,
command);
for(dap_command_entry* entry = dap_command_table; entry->command != NULL; entry++) {
if(strcmp(entry->command, command) == 0) {
entry->parser(py_arguments, &response_buffer);
break;
}
}
c11_sbuf__write_cstr(&response_buffer, "\"success\":true}");
c11_string* c11_string_response = c11_sbuf__submit(&response_buffer);
const char* response = c11_strdup(c11_string_response->data);
c11_string__delete(c11_string_response);
py_pop(); // py_arguments
py_pop(); // py_request
py_pop(); // py_command
return response;
}
void c11_dap_send_event(const char* event_name, const char* body_json) {
c11_sbuf buffer;
char header[64];
c11_sbuf__ctor(&buffer);
pk_sprintf(&buffer,
"{\"seq\":%d,\"type\":\"event\",\"event\":\"%s\",\"body\":%s}",
server.dap_next_seq++,
event_name,
body_json);
c11_string* json = c11_sbuf__submit(&buffer);
int json_len = json->size;
int header_len = snprintf(header, sizeof(header), "Content-Length: %d\r\n\r\n", json_len);
c11_socket_send(server.toclient, header, header_len);
c11_socket_send(server.toclient, json->data, json_len);
c11_string__delete(json);
}
void c11_dap_send_output_event(const char* category, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
c11_sbuf output;
c11_sbuf__ctor(&output);
pk_vsprintf(&output, fmt, args);
va_end(args);
c11_sbuf buffer;
c11_string* output_json = c11_sbuf__submit(&output);
c11_sv sv_output = {.data = output_json->data, .size = output_json->size};
c11_sbuf__ctor(&buffer);
pk_sprintf(&buffer, "{\"category\":\"%s\",\"output\":%Q}", category, sv_output);
c11_string* body_json = c11_sbuf__submit(&buffer);
c11_dap_send_event("output", body_json->data);
c11_string__delete(body_json);
c11_string__delete(output_json);
}
void c11_dap_send_stop_event(C11_STOP_REASON reason) {
if(reason == C11_DEBUGGER_NOSTOP) return;
const char* reason_str = "unknown";
switch(reason) {
case C11_DEBUGGER_STEP: reason_str = "step"; break;
case C11_DEBUGGER_EXCEPTION: reason_str = "exception"; break;
case C11_DEBUGGER_BP: reason_str = "breakpoint"; break;
default: break;
}
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "{\"reason\":\"%s\",\"threadId\":1,\"allThreadsStopped\":true", reason_str);
c11_sbuf__write_char(&buf, '}');
c11_string* body_json = c11_sbuf__submit(&buf);
c11_dap_send_event("stopped", body_json->data);
c11_string__delete(body_json);
}
void c11_dap_send_exited_event(int exitCode) {
char body[64];
snprintf(body, sizeof(body), "{\"exitCode\":%d}", exitCode);
c11_dap_send_event("exited", body);
}
void c11_dap_send_fatal_event(const char* message) {
char body[128];
snprintf(body, sizeof(body), "{\"message\":\"%s\"}", message);
c11_dap_send_event("pkpy/fatalError", body);
}
void c11_dap_send_initialized_event() { c11_dap_send_event("initialized", "{}"); }
int c11_dap_read_content_length(const char* buffer, int* header_length) {
const char* length_begin = strstr(buffer, "Content-Length: ");
if(!length_begin) {
printf("[DEBUGGER ERROR] : no Content-Length filed found\n");
*header_length = 0;
return -1;
}
length_begin += strlen("Content-Length: ");
const char* length_end = strstr(length_begin, "\r\n\r\n");
if(!length_end) {
printf("[DEBUGGER ERROR] : the seperator should br \\r\\n\\r\\n\n");
*header_length = 0;
return -1;
}
char* endptr = NULL;
long value = strtol(length_begin, &endptr, 10);
if(endptr == length_begin) {
printf("[DEBUGGER EORRO] : the length field is empty\n");
*header_length = 0;
return -1;
}
*header_length = (int)(endptr - buffer) + 4;
return (int)value;
}
const char* c11_dap_read_message() {
int message_length =
c11_socket_recv(server.toclient, server.buffer_begin, 1024 - server.buffer_length);
if(message_length == 0) {
printf("[DEBUGGER INFO] : client quit\n");
exit(0);
}
if(message_length < 0) { return NULL; }
server.buffer_length += message_length;
if(server.buffer_length == 0) return NULL;
int header_length;
int content_length = c11_dap_read_content_length(server.buffer_begin, &header_length);
if(content_length <= 0 || header_length <= 0) {
printf("[DEBUGGER ERROR]: invalid DAP header\n");
server.buffer_length = 0;
server.buffer_begin = server.buffer_data;
return NULL;
}
server.buffer_begin += header_length;
server.buffer_length -= header_length;
c11_sbuf result;
c11_sbuf__ctor(&result);
while(content_length > server.buffer_length) {
c11_sbuf__write_cstrn(&result, server.buffer_begin, server.buffer_length);
content_length -= server.buffer_length;
message_length = c11_socket_recv(server.toclient, server.buffer_data, 1024);
if(message_length == 0) {
printf("[DEBUGGER INFO] : client quit\n");
exit(0);
}
if(message_length < 0) continue;
server.buffer_begin = server.buffer_data;
server.buffer_length = message_length;
}
c11_sbuf__write_cstrn(&result, server.buffer_begin, content_length);
server.buffer_begin += content_length;
server.buffer_length -= content_length;
memmove(server.buffer_data, server.buffer_begin, server.buffer_length);
server.buffer_begin = server.buffer_data;
c11_string* tmp_result = c11_sbuf__submit(&result);
const char* dap_message = c11_strdup(tmp_result->data);
c11_string__delete(tmp_result);
return dap_message;
}
void c11_dap_init_server(const char* hostname, unsigned short port) {
server.dap_next_seq = 1;
server.isconfiguredone = false;
server.isclientready = false;
server.isfirstatttach = false;
server.isUserCode = false;
server.isAttached = false;
server.buffer_begin = server.buffer_data;
server.server = c11_socket_create(C11_AF_INET, C11_SOCK_STREAM, 0);
c11_socket_bind(server.server, hostname, port);
c11_socket_listen(server.server, 0);
// c11_dap_send_output_event("console", "[DEBUGGER INFO] : listen on %s:%hu\n",hostname,port);
printf("[DEBUGGER INFO] : listen on %s:%hu\n", hostname, port);
}
void c11_dap_waitforclient(const char* hostname, unsigned short port) {
server.toclient = c11_socket_accept(server.server, NULL, NULL);
}
inline static void c11_dap_handle_message() {
const char* message = c11_dap_read_message();
if(message == NULL) { return; }
// c11_dap_send_output_event("console", "[DEBUGGER LOG] : read request %s\n", message);
const char* response_content = c11_dap_handle_request(message);
if(response_content != NULL) {
// c11_dap_send_output_event("console",
// "[DEBUGGER LOG] : send response %s\n",
// response_content);
}
c11_sbuf buffer;
c11_sbuf__ctor(&buffer);
pk_sprintf(&buffer, "Content-Length: %d\r\n\r\n%s", strlen(response_content), response_content);
c11_string* response = c11_sbuf__submit(&buffer);
c11_socket_send(server.toclient, response->data, response->size);
PK_FREE((void*)message);
PK_FREE((void*)response_content);
c11_string__delete(response);
}
void c11_dap_configure_debugger() {
while(server.isconfiguredone == false) {
c11_dap_handle_message();
if(server.isfirstatttach) {
c11_dap_send_initialized_event();
server.isfirstatttach = false;
server.isAttached = true;
server.isUserCode = true;
} else if(server.isclientready) {
server.isclientready = false;
return;
}
}
// c11_dap_send_output_event("console", "[DEBUGGER INFO] : client configure done\n");
}
void c11_dap_tracefunc(py_Frame* frame, enum py_TraceEvent event) {
py_sys_settrace(NULL, false);
server.isUserCode = false;
C11_DEBUGGER_STATUS result = c11_debugger_on_trace(frame, event);
if(result == C11_DEBUGGER_EXIT) {
// c11_dap_send_output_event("console", "[DEBUGGER INFO] : program exit\n");
c11_dap_send_exited_event(0);
exit(0);
}
if(result != C11_DEBUGGER_SUCCESS) {
const char* message = NULL;
switch(result) {
case C11_DEBUGGER_FILEPATH_ERROR:
message = "Invalid py_file path: '..' forbidden, './' only allowed at start.";
break;
case C11_DEBUGGER_UNKNOW_ERROR:
default: message = "Unknown debugger failure."; break;
}
if(message) { c11_dap_send_fatal_event(message); }
c11_dap_send_exited_event(1);
exit(1);
}
c11_dap_handle_message();
C11_STOP_REASON reason = c11_debugger_should_pause();
if(reason == C11_DEBUGGER_NOSTOP) {
py_sys_settrace(c11_dap_tracefunc, false);
server.isUserCode = true;
return;
}
c11_dap_send_stop_event(reason);
while(c11_debugger_should_keep_pause()) {
c11_dap_handle_message();
}
server.isUserCode = true;
py_sys_settrace(c11_dap_tracefunc, false);
}
void py_debugger_waitforattach(const char* hostname, unsigned short port) {
c11_debugger_init();
c11_dap_init_server(hostname, port);
while(!server.isconfiguredone) {
c11_dap_waitforclient(hostname, port);
c11_dap_configure_debugger();
if(!server.isconfiguredone) {
c11_socket_close(server.toclient);
// c11_dap_send_output_event("console", "[DEBUGGER INFO] : An clinet is ready\n");
}
}
c11_socket_set_block(server.toclient, 0);
py_sys_settrace(c11_dap_tracefunc, true);
}
void py_debugger_exit(int exitCode) { c11_dap_send_exited_event(exitCode); }
int py_debugger_status() {
if(!server.isAttached) {
return 0;
}
return server.isUserCode ? 1 : 2;
}
void py_debugger_exceptionbreakpoint(py_Ref exc) {
assert(py_isinstance(exc, tp_BaseException));
py_sys_settrace(NULL, true);
server.isUserCode = false;
c11_debugger_exception_on_trace(exc);
for(;;) {
C11_STOP_REASON reason = c11_debugger_should_pause();
c11_dap_send_stop_event(reason);
while(c11_debugger_should_keep_pause()) {
c11_dap_handle_message();
}
}
}
#endif // PK_ENABLE_OS
// src/interpreter\ceval.c
#include <stdbool.h>
#include <assert.h>
#include <time.h>
#define DISPATCH() \
do { \
frame->ip++; \
goto __NEXT_STEP; \
} while(0)
#define DISPATCH_JUMP(__offset) \
do { \
frame->ip += __offset; \
goto __NEXT_STEP; \
} while(0)
#define DISPATCH_JUMP_ABSOLUTE(__target) \
do { \
frame->ip = __target; \
goto __NEXT_STEP; \
} while(0)
#define RESET_CO_CACHE() \
do { \
co_codes = frame->co->codes.data; \
co_names = frame->co->names.data; \
} while(0)
/* Stack manipulation macros */
// https://github.com/python/cpython/blob/3.9/Python/ceval.c#L1123
#define TOP() (self->stack.sp - 1)
#define SECOND() (self->stack.sp - 2)
#define THIRD() (self->stack.sp - 3)
#define FOURTH() (self->stack.sp - 4)
#define STACK_SHRINK(n) (self->stack.sp -= n)
#define STACK_GROW(n) (self->stack.sp += n)
#define PUSH(v) \
do { \
*self->stack.sp = *(v); \
self->stack.sp++; \
} while(0)
#define POP() (--self->stack.sp)
#define POPX() (*--self->stack.sp)
#define SP() (self->stack.sp)
// [a, b] -> [?, a, b]
#define INSERT_THIRD() \
do { \
PUSH(TOP()); \
*SECOND() = *THIRD(); \
} while(0)
// Must use a DISPATCH() after vectorcall_opcall() immediately!
#define vectorcall_opcall(argc, kwargc) \
do { \
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
switch(res) { \
case RES_RETURN: PUSH(&self->last_retval); break; \
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
case RES_ERROR: goto __ERROR; \
default: c11__unreachable(); \
} \
} while(0)
static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
py_TValue** p = ctx;
if(py_isstr(key)) {
py_Name name = py_namev(py_tosv(key));
py_newint(*p, (uintptr_t)name);
py_assign(*p + 1, val);
(*p) += 2;
return true;
}
return TypeError("keywords must be strings, not '%t'", key->type);
}
FrameResult VM__run_top_frame(VM* self) {
py_Frame* frame = self->top_frame;
Bytecode* co_codes;
py_Name* co_names;
Bytecode byte;
const py_Frame* base_frame = frame;
__NEXT_FRAME:
if(self->recursion_depth >= self->max_recursion_depth) {
py_exception(tp_RecursionError, "maximum recursion depth exceeded");
goto __ERROR;
}
RESET_CO_CACHE();
frame->ip++;
__NEXT_STEP:
byte = co_codes[frame->ip];
if(self->trace_info.func) {
bool is_virtual = byte.op == OP_RETURN_VALUE && byte.arg == BC_RETURN_VIRTUAL;
if(!is_virtual) {
SourceLocation loc = Frame__source_location(frame);
SourceLocation prev_loc = self->trace_info.prev_loc;
if(loc.lineno != prev_loc.lineno || loc.src != prev_loc.src) {
if(prev_loc.src) PK_DECREF(prev_loc.src);
PK_INCREF(loc.src);
self->trace_info.prev_loc = loc;
self->trace_info.func(frame, TRACE_EVENT_LINE);
}
}
}
#if PK_ENABLE_WATCHDOG
if(self->watchdog_info.max_reset_time > 0) {
if(py_debugger_status() == 0 && clock() > self->watchdog_info.max_reset_time) {
self->watchdog_info.max_reset_time = 0;
TimeoutError("watchdog timeout");
goto __ERROR;
}
}
#endif
#ifndef NDEBUG
pk_print_stack(self, frame, byte);
#endif
switch((Opcode)byte.op) {
case OP_NO_OP: DISPATCH();
/*****************************************/
case OP_POP_TOP: POP(); DISPATCH();
case OP_DUP_TOP: PUSH(TOP()); DISPATCH();
case OP_DUP_TOP_TWO:
// [a, b]
PUSH(SECOND()); // [a, b, a]
PUSH(SECOND()); // [a, b, a, b]
DISPATCH();
case OP_ROT_TWO: {
py_TValue tmp = *TOP();
*TOP() = *SECOND();
*SECOND() = tmp;
DISPATCH();
}
case OP_ROT_THREE: {
// [a, b, c] -> [c, a, b]
py_TValue tmp = *TOP();
*TOP() = *SECOND();
*SECOND() = *THIRD();
*THIRD() = tmp;
DISPATCH();
}
case OP_PRINT_EXPR: {
if(self->callbacks.displayhook) {
bool ok = self->callbacks.displayhook(TOP());
if(!ok) goto __ERROR;
} else {
if(TOP()->type != tp_NoneType) {
bool ok = py_repr(TOP());
if(!ok) goto __ERROR;
self->callbacks.print(py_tostr(&self->last_retval));
self->callbacks.print("\n");
}
}
POP();
DISPATCH();
}
/*****************************************/
case OP_LOAD_CONST: {
PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg));
DISPATCH();
}
case OP_LOAD_NONE: {
py_newnone(SP()++);
DISPATCH();
}
case OP_LOAD_TRUE: {
py_newbool(SP()++, true);
DISPATCH();
}
case OP_LOAD_FALSE: {
py_newbool(SP()++, false);
DISPATCH();
}
/*****************************************/
case OP_LOAD_SMALL_INT: {
py_newint(SP()++, (int16_t)byte.arg);
DISPATCH();
}
case OP_LOAD_NAME_AS_INT: {
py_Name name = co_names[byte.arg];
py_newint(SP()++, (uintptr_t)name);
DISPATCH();
}
/*****************************************/
case OP_LOAD_ELLIPSIS: {
py_newellipsis(SP()++);
DISPATCH();
}
case OP_LOAD_FUNCTION: {
FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
Function__ctor(ud, decl, frame->module, frame->globals);
if(decl->nested) {
if(frame->is_locals_special) {
RuntimeError("cannot create closure from special locals");
goto __ERROR;
}
ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
py_Name name = py_name(decl->code.name->data);
// capture itself to allow recursion
NameDict__set(ud->closure, name, SP());
} else {
if(self->curr_class) ud->clazz = self->curr_class->_obj;
}
SP()++;
DISPATCH();
}
case OP_LOAD_NULL:
py_newnil(SP()++);
DISPATCH();
/*****************************************/
case OP_LOAD_FAST: {
assert(!frame->is_locals_special);
py_Ref val = &frame->locals[byte.arg];
if(!py_isnil(val)) {
PUSH(val);
DISPATCH();
}
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
UnboundLocalError(name);
goto __ERROR;
}
case OP_LOAD_NAME: {
assert(frame->is_locals_special);
py_Name name = co_names[byte.arg];
// locals
switch(frame->locals->type) {
case tp_locals: {
py_Frame* noproxy = frame->locals->_ptr;
py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
if(slot == NULL) break;
if(py_isnil(slot)) {
UnboundLocalError(name);
goto __ERROR;
}
PUSH(slot);
DISPATCH();
}
case tp_dict: {
int res = py_dict_getitem(frame->locals, py_name2ref(name));
if(res == 1) {
PUSH(&self->last_retval);
DISPATCH();
}
if(res == 0) break;
assert(res == -1);
goto __ERROR;
}
case tp_nil: break;
default: c11__unreachable();
}
// globals
int res = Frame__getglobal(frame, name);
if(res == 1) {
PUSH(&self->last_retval);
DISPATCH();
}
if(res == -1) goto __ERROR;
// builtins
py_Ref tmp = py_getdict(self->builtins, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
NameError(name);
goto __ERROR;
}
case OP_LOAD_NONLOCAL: {
py_Name name = co_names[byte.arg];
py_Ref tmp = Frame__getclosure(frame, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
int res = Frame__getglobal(frame, name);
if(res == 1) {
PUSH(&self->last_retval);
DISPATCH();
}
if(res == -1) goto __ERROR;
tmp = py_getdict(self->builtins, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
NameError(name);
goto __ERROR;
}
case OP_LOAD_GLOBAL: {
py_Name name = co_names[byte.arg];
int res = Frame__getglobal(frame, name);
if(res == 1) {
PUSH(&self->last_retval);
DISPATCH();
}
if(res == -1) goto __ERROR;
py_Ref tmp = py_getdict(self->builtins, name);
if(tmp != NULL) {
PUSH(tmp);
DISPATCH();
}
NameError(name);
goto __ERROR;
}
case OP_LOAD_ATTR: {
py_Name name = co_names[byte.arg];
if(py_getattr(TOP(), name)) {
py_assign(TOP(), py_retval());
} else {
goto __ERROR;
}
DISPATCH();
}
case OP_LOAD_CLASS_GLOBAL: {
assert(self->curr_class);
py_Name name = co_names[byte.arg];
py_Ref tmp = py_getdict(self->curr_class, name);
if(tmp) {
PUSH(tmp);
DISPATCH();
}
// load global if attribute not found
int res = Frame__getglobal(frame, name);
if(res == 1) {
PUSH(&self->last_retval);
DISPATCH();
}
if(res == -1) goto __ERROR;
tmp = py_getdict(self->builtins, name);
if(tmp) {
PUSH(tmp);
DISPATCH();
}
NameError(name);
goto __ERROR;
}
case OP_LOAD_METHOD: {
// [self] -> [unbound, self]
py_Name name = co_names[byte.arg];
bool ok = py_pushmethod(name);
if(!ok) {
// fallback to getattr
if(py_getattr(TOP(), name)) {
py_assign(TOP(), py_retval());
py_newnil(SP()++);
} else {
goto __ERROR;
}
}
DISPATCH();
}
case OP_LOAD_SUBSCR: {
// [a, b] -> a[b]
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
if(magic) {
if(magic->type == tp_nativefunc) {
if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
POP();
py_assign(TOP(), py_retval());
} else {
INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__getitem__, a, b]
vectorcall_opcall(1, 0);
}
DISPATCH();
}
TypeError("'%t' object is not subscriptable", SECOND()->type);
goto __ERROR;
}
case OP_STORE_FAST: {
assert(!frame->is_locals_special);
frame->locals[byte.arg] = POPX();
DISPATCH();
}
case OP_STORE_NAME: {
assert(frame->is_locals_special);
py_Name name = co_names[byte.arg];
switch(frame->locals->type) {
case tp_locals: {
py_Frame* noproxy = frame->locals->_ptr;
py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
if(slot == NULL) {
UnboundLocalError(name);
goto __ERROR;
}
*slot = POPX();
DISPATCH();
}
case tp_dict: {
if(!py_dict_setitem(frame->locals, py_name2ref(name), TOP())) goto __ERROR;
POP();
DISPATCH();
}
case tp_nil: {
// globals
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
POP();
DISPATCH();
}
default: c11__unreachable();
}
}
case OP_STORE_GLOBAL: {
py_Name name = co_names[byte.arg];
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
POP();
DISPATCH();
}
case OP_STORE_ATTR: {
// [val, a] -> a.b = val
py_Name name = co_names[byte.arg];
if(!py_setattr(TOP(), name, SECOND())) goto __ERROR;
STACK_SHRINK(2);
DISPATCH();
}
case OP_STORE_SUBSCR: {
// [val, a, b] -> a[b] = val
py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
if(magic) {
PUSH(THIRD()); // [val, a, b, val]
if(magic->type == tp_nativefunc) {
if(!py_callcfunc(magic->_cfunc, 3, THIRD())) goto __ERROR;
STACK_SHRINK(4);
} else {
*FOURTH() = *magic; // [__setitem__, a, b, val]
if(!py_vectorcall(2, 0)) goto __ERROR;
}
DISPATCH();
}
TypeError("'%t' object does not support item assignment", SECOND()->type);
goto __ERROR;
}
case OP_DELETE_FAST: {
assert(!frame->is_locals_special);
py_Ref tmp = &frame->locals[byte.arg];
if(py_isnil(tmp)) {
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
UnboundLocalError(name);
goto __ERROR;
}
py_newnil(tmp);
DISPATCH();
}
case OP_DELETE_NAME: {
assert(frame->is_locals_special);
py_Name name = co_names[byte.arg];
switch(frame->locals->type) {
case tp_locals: {
py_Frame* noproxy = frame->locals->_ptr;
py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
if(slot == NULL || py_isnil(slot)) {
UnboundLocalError(name);
goto __ERROR;
}
py_newnil(slot);
DISPATCH();
}
case tp_dict: {
int res = py_dict_delitem(frame->locals, py_name2ref(name));
if(res == 1) DISPATCH();
if(res == 0) UnboundLocalError(name);
goto __ERROR;
}
case tp_nil: {
// globals
int res = Frame__delglobal(frame, name);
if(res == 1) DISPATCH();
if(res == 0) NameError(name);
goto __ERROR;
}
default: c11__unreachable();
}
}
case OP_DELETE_GLOBAL: {
py_Name name = co_names[byte.arg];
int res = Frame__delglobal(frame, name);
if(res == 1) DISPATCH();
if(res == -1) goto __ERROR;
NameError(name);
goto __ERROR;
}
case OP_DELETE_ATTR: {
py_Name name = co_names[byte.arg];
if(!py_delattr(TOP(), name)) goto __ERROR;
DISPATCH();
}
case OP_DELETE_SUBSCR: {
// [a, b] -> del a[b]
py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
if(magic) {
if(magic->type == tp_nativefunc) {
if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
STACK_SHRINK(2);
} else {
INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__delitem__, a, b]
if(!py_vectorcall(1, 0)) goto __ERROR;
}
DISPATCH();
}
TypeError("'%t' object does not support item deletion", SECOND()->type);
goto __ERROR;
}
/*****************************************/
case OP_BUILD_IMAG: {
// [x]
py_Ref f = py_getdict(self->builtins, py_name("complex"));
assert(f != NULL);
py_TValue tmp = *TOP();
*TOP() = *f; // [complex]
py_newnil(SP()++); // [complex, NULL]
py_newint(SP()++, 0); // [complex, NULL, 0]
*SP()++ = tmp; // [complex, NULL, 0, x]
vectorcall_opcall(2, 0);
DISPATCH();
}
case OP_BUILD_BYTES: {
int size;
py_Ref string = c11__at(py_TValue, &frame->co->consts, byte.arg);
const char* data = py_tostrn(string, &size);
unsigned char* p = py_newbytes(SP()++, size);
memcpy(p, data, size);
DISPATCH();
}
case OP_BUILD_TUPLE: {
py_TValue tmp;
py_Ref p = py_newtuple(&tmp, byte.arg);
py_TValue* begin = SP() - byte.arg;
for(int i = 0; i < byte.arg; i++)
p[i] = begin[i];
SP() = begin;
PUSH(&tmp);
DISPATCH();
}
case OP_BUILD_LIST: {
py_TValue tmp;
py_newlistn(&tmp, byte.arg);
py_TValue* begin = SP() - byte.arg;
for(int i = 0; i < byte.arg; i++) {
py_list_setitem(&tmp, i, begin + i);
}
SP() = begin;
PUSH(&tmp);
DISPATCH();
}
case OP_BUILD_DICT: {
py_TValue* begin = SP() - byte.arg * 2;
py_Ref tmp = py_pushtmp();
py_newdict(tmp);
for(int i = 0; i < byte.arg * 2; i += 2) {
bool ok = py_dict_setitem(tmp, begin + i, begin + i + 1);
if(!ok) goto __ERROR;
}
SP() = begin;
PUSH(tmp);
DISPATCH();
}
case OP_BUILD_SET: {
py_TValue* begin = SP() - byte.arg;
py_Ref typeobject_set = py_getdict(self->builtins, py_name("set"));
assert(typeobject_set != NULL);
py_push(typeobject_set);
py_pushnil();
if(!py_vectorcall(0, 0)) goto __ERROR;
py_push(py_retval()); // empty set
py_Name id_add = py_name("add");
for(int i = 0; i < byte.arg; i++) {
py_push(TOP());
if(!py_pushmethod(id_add)) {
c11__abort("OP_BUILD_SET: failed to load method 'add'");
}
py_push(begin + i);
if(!py_vectorcall(1, 0)) goto __ERROR;
}
py_TValue tmp = *TOP();
SP() = begin;
PUSH(&tmp);
DISPATCH();
}
case OP_BUILD_SLICE: {
// [start, stop, step]
py_TValue tmp;
py_ObjectRef slots = py_newslice(&tmp);
slots[0] = *THIRD();
slots[1] = *SECOND();
slots[2] = *TOP();
STACK_SHRINK(3);
PUSH(&tmp);
DISPATCH();
}
case OP_BUILD_STRING: {
py_TValue* begin = SP() - byte.arg;
c11_sbuf ss;
c11_sbuf__ctor(&ss);
for(int i = 0; i < byte.arg; i++) {
if(!py_str(begin + i)) goto __ERROR;
c11_sbuf__write_sv(&ss, py_tosv(&self->last_retval));
}
SP() = begin;
c11_sbuf__py_submit(&ss, SP()++);
DISPATCH();
}
/*****************************/
#define CASE_BINARY_OP(label, op, rop) \
case label: { \
if(!pk_stack_binaryop(self, op, rop)) goto __ERROR; \
POP(); \
*TOP() = self->last_retval; \
DISPATCH(); \
}
CASE_BINARY_OP(OP_BINARY_ADD, __add__, __radd__)
CASE_BINARY_OP(OP_BINARY_SUB, __sub__, __rsub__)
CASE_BINARY_OP(OP_BINARY_MUL, __mul__, __rmul__)
CASE_BINARY_OP(OP_BINARY_TRUEDIV, __truediv__, __rtruediv__)
CASE_BINARY_OP(OP_BINARY_FLOORDIV, __floordiv__, __rfloordiv__)
CASE_BINARY_OP(OP_BINARY_MOD, __mod__, __rmod__)
CASE_BINARY_OP(OP_BINARY_POW, __pow__, __rpow__)
CASE_BINARY_OP(OP_BINARY_LSHIFT, __lshift__, 0)
CASE_BINARY_OP(OP_BINARY_RSHIFT, __rshift__, 0)
CASE_BINARY_OP(OP_BINARY_AND, __and__, 0)
CASE_BINARY_OP(OP_BINARY_OR, __or__, 0)
CASE_BINARY_OP(OP_BINARY_XOR, __xor__, 0)
CASE_BINARY_OP(OP_BINARY_MATMUL, __matmul__, 0)
CASE_BINARY_OP(OP_COMPARE_LT, __lt__, __gt__)
CASE_BINARY_OP(OP_COMPARE_LE, __le__, __ge__)
CASE_BINARY_OP(OP_COMPARE_EQ, __eq__, __eq__)
CASE_BINARY_OP(OP_COMPARE_NE, __ne__, __ne__)
CASE_BINARY_OP(OP_COMPARE_GT, __gt__, __lt__)
CASE_BINARY_OP(OP_COMPARE_GE, __ge__, __le__)
#undef CASE_BINARY_OP
case OP_IS_OP: {
bool res = py_isidentical(SECOND(), TOP());
POP();
if(byte.arg) res = !res;
py_newbool(TOP(), res);
DISPATCH();
}
case OP_CONTAINS_OP: {
// [b, a] -> b __contains__ a (a in b) -> [retval]
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
if(magic) {
if(magic->type == tp_nativefunc) {
if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
STACK_SHRINK(2);
} else {
INSERT_THIRD(); // [?, b, a]
*THIRD() = *magic; // [__contains__, a, b]
if(!py_vectorcall(1, 0)) goto __ERROR;
}
bool res = py_tobool(py_retval());
if(byte.arg) res = !res;
py_newbool(SP()++, res);
DISPATCH();
}
TypeError("'%t' type does not support '__contains__'", SECOND()->type);
goto __ERROR;
}
/*****************************************/
case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg);
case OP_POP_JUMP_IF_NOT_MATCH: {
int res = py_equal(SECOND(), TOP());
if(res < 0) goto __ERROR;
STACK_SHRINK(2);
if(!res) DISPATCH_JUMP((int16_t)byte.arg);
DISPATCH();
}
case OP_POP_JUMP_IF_FALSE: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
POP();
if(!res) DISPATCH_JUMP((int16_t)byte.arg);
DISPATCH();
}
case OP_POP_JUMP_IF_TRUE: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
POP();
if(res) DISPATCH_JUMP((int16_t)byte.arg);
DISPATCH();
}
case OP_JUMP_IF_TRUE_OR_POP: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
if(res) {
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP();
DISPATCH();
}
}
case OP_JUMP_IF_FALSE_OR_POP: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
if(!res) {
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP();
DISPATCH();
}
}
case OP_SHORTCUT_IF_FALSE_OR_POP: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
if(!res) { // [b, False]
STACK_SHRINK(2); // []
py_newbool(SP()++, false); // [False]
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP(); // [b]
DISPATCH();
}
}
case OP_LOOP_CONTINUE: {
DISPATCH_JUMP((int16_t)byte.arg);
}
case OP_LOOP_BREAK: {
DISPATCH_JUMP((int16_t)byte.arg);
}
/*****************************************/
case OP_CALL: {
if(self->heap.gc_enabled) ManagedHeap__collect_hint(&self->heap);
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
DISPATCH();
}
case OP_CALL_VARGS: {
// [_0, _1, _2 | k1, v1, k2, v2]
uint16_t argc = byte.arg & 0xFF;
uint16_t kwargc = byte.arg >> 8;
int n = 0;
py_TValue* sp = SP();
py_TValue* p1 = sp - kwargc * 2;
py_TValue* base = p1 - argc;
py_TValue* buf = self->vectorcall_buffer;
for(py_TValue* curr = base; curr != p1; curr++) {
if(curr->type != tp_star_wrapper) {
buf[n++] = *curr;
} else {
py_TValue* args = py_getslot(curr, 0);
py_TValue* p;
int length = pk_arrayview(args, &p);
if(length != -1) {
for(int j = 0; j < length; j++) {
buf[n++] = p[j];
}
argc += length - 1;
} else {
TypeError("*args must be a list or tuple, got '%t'", args->type);
goto __ERROR;
}
}
}
for(py_TValue* curr = p1; curr != sp; curr += 2) {
if(curr[1].type != tp_star_wrapper) {
buf[n++] = curr[0];
buf[n++] = curr[1];
} else {
assert(py_toint(&curr[0]) == 0);
py_TValue* kwargs = py_getslot(&curr[1], 0);
if(kwargs->type == tp_dict) {
py_TValue* p = buf + n;
if(!py_dict_apply(kwargs, unpack_dict_to_buffer, &p)) goto __ERROR;
n = p - buf;
kwargc += py_dict_len(kwargs) - 1;
} else {
TypeError("**kwargs must be a dict, got '%t'", kwargs->type);
goto __ERROR;
}
}
}
memcpy(base, buf, n * sizeof(py_TValue));
SP() = base + n;
vectorcall_opcall(argc, kwargc);
DISPATCH();
}
case OP_RETURN_VALUE: {
if(byte.arg == BC_NOARG) {
self->last_retval = POPX();
} else {
py_newnone(&self->last_retval);
}
VM__pop_frame(self);
if(frame == base_frame) { // [ frameBase<- ]
return RES_RETURN;
} else {
frame = self->top_frame;
PUSH(&self->last_retval);
goto __NEXT_FRAME;
}
DISPATCH();
}
case OP_YIELD_VALUE: {
if(byte.arg == 1) {
py_newnone(py_retval());
} else {
py_assign(py_retval(), TOP());
POP();
}
return RES_YIELD;
}
case OP_FOR_ITER_YIELD_VALUE: {
int res = py_next(TOP());
if(res == -1) goto __ERROR;
if(res) {
return RES_YIELD;
} else {
assert(self->last_retval.type == tp_StopIteration);
BaseException* ud = py_touserdata(py_retval());
py_ObjectRef value = &ud->args;
if(py_isnil(value)) value = py_None();
*TOP() = *value; // [iter] -> [retval]
DISPATCH_JUMP((int16_t)byte.arg);
}
}
/////////
case OP_LIST_APPEND: {
// [list, iter, value]
py_list_append(THIRD(), TOP());
POP();
DISPATCH();
}
case OP_DICT_ADD: {
// [dict, iter, key, value]
bool ok = py_dict_setitem(FOURTH(), SECOND(), TOP());
if(!ok) goto __ERROR;
STACK_SHRINK(2);
DISPATCH();
}
case OP_SET_ADD: {
// [set, iter, value]
py_push(THIRD()); // [| set]
if(!py_pushmethod(py_name("add"))) {
c11__abort("OP_SET_ADD: failed to load method 'add'");
} // [|add() set]
py_push(THIRD());
if(!py_vectorcall(1, 0)) goto __ERROR;
POP();
DISPATCH();
}
/////////
case OP_UNARY_NEGATIVE: {
if(!pk_callmagic(__neg__, 1, TOP())) goto __ERROR;
*TOP() = self->last_retval;
DISPATCH();
}
case OP_UNARY_NOT: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
py_newbool(TOP(), !res);
DISPATCH();
}
case OP_UNARY_STAR: {
py_TValue value = POPX();
int* level = py_newobject(SP()++, tp_star_wrapper, 1, sizeof(int));
*level = byte.arg;
py_setslot(TOP(), 0, &value);
DISPATCH();
}
case OP_UNARY_INVERT: {
if(!pk_callmagic(__invert__, 1, TOP())) goto __ERROR;
*TOP() = self->last_retval;
DISPATCH();
}
////////////////
case OP_GET_ITER: {
if(!py_iter(TOP())) goto __ERROR;
*TOP() = *py_retval();
DISPATCH();
}
case OP_FOR_ITER: {
int res = py_next(TOP());
if(res == -1) goto __ERROR;
if(res) {
PUSH(py_retval());
DISPATCH();
} else {
assert(self->last_retval.type == tp_StopIteration);
POP(); // [iter] -> []
DISPATCH_JUMP((int16_t)byte.arg);
}
}
////////
case OP_IMPORT_PATH: {
py_Ref path_object = c11__at(py_TValue, &frame->co->consts, byte.arg);
const char* path = py_tostr(path_object);
int res = py_import(path);
if(res == -1) goto __ERROR;
if(res == 0) {
ImportError("No module named '%s'", path);
goto __ERROR;
}
PUSH(py_retval());
DISPATCH();
}
case OP_POP_IMPORT_STAR: {
// [module]
NameDict* dict = PyObject__dict(TOP()->_obj);
py_ItemRef all = NameDict__try_get(dict, __all__);
if(all) {
py_TValue* p;
int length = pk_arrayview(all, &p);
if(length == -1) {
TypeError("'__all__' must be a list or tuple, got '%t'", all->type);
goto __ERROR;
}
for(int i = 0; i < length; i++) {
py_Name name = py_namev(py_tosv(p + i));
py_ItemRef value = NameDict__try_get(dict, name);
if(value == NULL) {
ImportError("cannot import name '%n'", name);
goto __ERROR;
} else {
if(!Frame__setglobal(frame, name, value)) goto __ERROR;
}
}
} else {
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
c11_sv name = py_name2sv(kv->key);
if(name.size == 0 || name.data[0] == '_') continue;
if(!Frame__setglobal(frame, kv->key, &kv->value)) goto __ERROR;
}
}
POP();
DISPATCH();
}
////////
case OP_UNPACK_SEQUENCE: {
py_TValue* p;
int length;
switch(TOP()->type) {
case tp_tuple: {
length = py_tuple_len(TOP());
p = py_tuple_data(TOP());
break;
}
case tp_list: {
length = py_list_len(TOP());
p = py_list_data(TOP());
break;
}
case tp_vec2i: {
length = 2;
if(byte.arg != length) break;
c11_vec2i val = py_tovec2i(TOP());
POP();
py_newint(SP()++, val.x);
py_newint(SP()++, val.y);
DISPATCH();
}
case tp_vec2: {
length = 2;
if(byte.arg != length) break;
c11_vec2 val = py_tovec2(TOP());
POP();
py_newfloat(SP()++, val.x);
py_newfloat(SP()++, val.y);
DISPATCH();
}
case tp_vec3i: {
length = 3;
if(byte.arg != length) break;
c11_vec3i val = py_tovec3i(TOP());
POP();
py_newint(SP()++, val.x);
py_newint(SP()++, val.y);
py_newint(SP()++, val.z);
DISPATCH();
}
case tp_vec3: {
length = 3;
if(byte.arg != length) break;
c11_vec3 val = py_tovec3(TOP());
POP();
py_newfloat(SP()++, val.x);
py_newfloat(SP()++, val.y);
py_newfloat(SP()++, val.z);
DISPATCH();
}
default: {
TypeError("expected list or tuple to unpack, got %t", TOP()->type);
goto __ERROR;
}
}
if(length != byte.arg) {
ValueError("expected %d values to unpack, got %d", byte.arg, length);
goto __ERROR;
}
POP();
for(int i = 0; i < length; i++) {
PUSH(p + i);
}
DISPATCH();
}
case OP_UNPACK_EX: {
py_TValue* p;
int length = pk_arrayview(TOP(), &p);
if(length == -1) {
TypeError("expected list or tuple to unpack, got %t", TOP()->type);
goto __ERROR;
}
int exceed = length - byte.arg;
if(exceed < 0) {
ValueError("not enough values to unpack");
goto __ERROR;
}
POP();
for(int i = 0; i < byte.arg; i++) {
PUSH(p + i);
}
py_newlistn(SP()++, exceed);
for(int i = 0; i < exceed; i++) {
py_list_setitem(TOP(), i, p + byte.arg + i);
}
DISPATCH();
}
///////////
case OP_BEGIN_CLASS: {
// [base]
py_Name name = co_names[byte.arg];
py_Type base;
if(py_isnone(TOP())) {
base = tp_object;
} else {
if(!py_checktype(TOP(), tp_type)) goto __ERROR;
base = py_totype(TOP());
}
POP();
py_TypeInfo* base_ti = pk_typeinfo(base);
if(base_ti->is_final) {
TypeError("type '%t' is not an acceptable base type", base);
goto __ERROR;
}
py_Type type = pk_newtypewithmode(name,
base,
frame->module,
NULL,
base_ti->is_python,
false,
frame->co->src->mode);
PUSH(py_tpobject(type));
self->curr_class = TOP();
DISPATCH();
}
case OP_END_CLASS: {
// [cls or decorated]
py_Name name = co_names[byte.arg];
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
if(py_istype(TOP(), tp_type)) {
// call on_end_subclass
py_TypeInfo* ti = py_touserdata(TOP());
if(ti->base != tp_object) {
py_TypeInfo* base_ti = ti->base_ti;
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
}
py_TValue* slot_eq = py_getdict(&ti->self, __eq__);
py_TValue* slot_ne = py_getdict(&ti->self, __ne__);
if(slot_eq && !slot_ne) {
TypeError("'%n' implements '__eq__' but not '__ne__'", ti->name);
goto __ERROR;
}
}
// class with decorator is unsafe currently
// it skips the above check
POP();
self->curr_class = NULL;
DISPATCH();
}
case OP_STORE_CLASS_ATTR: {
assert(self->curr_class);
py_Name name = co_names[byte.arg];
// TOP() can be a function, classmethod or custom decorator
py_setdict(self->curr_class, name, TOP());
POP();
DISPATCH();
}
case OP_ADD_CLASS_ANNOTATION: {
assert(self->curr_class);
// [type_hint string]
py_TypeInfo* ti = py_touserdata(self->curr_class);
if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations);
py_Name name = co_names[byte.arg];
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(name), TOP());
if(!ok) goto __ERROR;
POP();
DISPATCH();
}
///////////
case OP_WITH_ENTER: {
// [expr]
py_push(TOP());
if(!py_pushmethod(__enter__)) {
TypeError("'%t' object does not support the context manager protocol", TOP()->type);
goto __ERROR;
}
vectorcall_opcall(0, 0);
DISPATCH();
}
case OP_WITH_EXIT: {
// [expr]
py_push(TOP());
if(!py_pushmethod(__exit__)) {
TypeError("'%t' object does not support the context manager protocol", TOP()->type);
goto __ERROR;
}
if(!py_vectorcall(0, 0)) goto __ERROR;
POP();
DISPATCH();
}
///////////
case OP_BEGIN_TRY: {
Frame__begin_try(frame, SP());
DISPATCH();
}
case OP_END_TRY: {
c11_vector__pop(&frame->exc_stack);
DISPATCH();
}
case OP_EXCEPTION_MATCH: {
bool ok = false;
bool has_invalid = false;
if(TOP()->type == tp_type) {
ok = py_isinstance(&self->unhandled_exc, py_totype(TOP()));
} else if(TOP()->type == tp_tuple) {
int len = py_tuple_len(TOP());
py_ObjectRef data = py_tuple_data(TOP());
for(int i = 0; i < len; i++) {
if((data + i)->type != tp_type) {
has_invalid = true;
break;
}
}
if(!has_invalid) {
for(int i = 0; i < len; i++) {
if(py_isinstance(&self->unhandled_exc, py_totype(data + i))) {
ok = true;
break;
}
}
}
} else {
has_invalid = true;
}
if(has_invalid) {
py_newnil(&self->unhandled_exc);
TypeError("catching classes that do not inherit from BaseException is not allowed");
c11_vector__pop(&frame->exc_stack);
goto __ERROR;
} else {
py_newbool(TOP(), ok);
DISPATCH();
}
}
case OP_HANDLE_EXCEPTION: {
FrameExcInfo* info = Frame__top_exc_info(frame);
assert(info != NULL && py_isnil(&info->exc));
info->exc = self->unhandled_exc;
py_newnil(&self->unhandled_exc);
DISPATCH();
}
case OP_RAISE: {
// [exception]
if(py_istype(TOP(), tp_type)) {
if(!py_tpcall(py_totype(TOP()), 0, NULL)) goto __ERROR;
py_assign(TOP(), py_retval());
}
if(!py_isinstance(TOP(), tp_BaseException)) {
TypeError("exceptions must derive from BaseException");
goto __ERROR;
}
py_raise(TOP());
goto __ERROR;
}
case OP_RAISE_ASSERT: {
if(byte.arg) {
if(!py_str(TOP())) goto __ERROR;
POP();
py_exception(tp_AssertionError, "%s", py_tostr(py_retval()));
} else {
py_exception(tp_AssertionError, "");
}
goto __ERROR;
}
case OP_RE_RAISE: {
if(py_isnil(&self->unhandled_exc)) {
FrameExcInfo* info = Frame__top_exc_info(frame);
assert(info != NULL && !py_isnil(&info->exc));
self->unhandled_exc = info->exc;
}
c11_vector__pop(&frame->exc_stack);
goto __ERROR_RE_RAISE;
}
case OP_PUSH_EXCEPTION: {
FrameExcInfo* info = Frame__top_exc_info(frame);
assert(info != NULL && !py_isnil(&info->exc));
PUSH(&info->exc);
DISPATCH();
}
//////////////////
case OP_FORMAT_STRING: {
py_Ref spec = c11__at(py_TValue, &frame->co->consts, byte.arg);
bool ok = pk_format_object(self, TOP(), py_tosv(spec));
if(!ok) goto __ERROR;
py_assign(TOP(), py_retval());
DISPATCH();
}
default: c11__unreachable();
}
c11__unreachable();
__ERROR:
assert(!py_isnil(&self->unhandled_exc));
py_BaseException__stpush(frame,
&self->unhandled_exc,
frame->co->src,
Frame__lineno(frame),
!frame->is_locals_special ? frame->co->name->data : NULL);
__ERROR_RE_RAISE:
do {
self->curr_class = NULL;
self->curr_function = NULL;
} while(0);
int target = Frame__goto_exception_handler(frame, &self->stack, &self->unhandled_exc);
if(target >= 0) {
// 1. Exception can be handled inside the current frame
DISPATCH_JUMP_ABSOLUTE(target);
} else {
// 2. Exception need to be propagated to the upper frame
bool is_base_frame_to_be_popped = frame == base_frame;
VM__pop_frame(self);
if(self->top_frame == NULL || is_base_frame_to_be_popped) {
// propagate to the top level
return RES_ERROR;
}
frame = self->top_frame;
RESET_CO_CACHE();
goto __ERROR;
}
c11__unreachable();
}
const char* pk_op2str(py_Name op) {
if(__eq__ == op) return "==";
if(__ne__ == op) return "!=";
if(__lt__ == op) return "<";
if(__le__ == op) return "<=";
if(__gt__ == op) return ">";
if(__ge__ == op) return ">=";
if(__add__ == op) return "+";
if(__sub__ == op) return "-";
if(__mul__ == op) return "*";
if(__truediv__ == op) return "/";
if(__floordiv__ == op) return "//";
if(__mod__ == op) return "%";
if(__pow__ == op) return "**";
if(__lshift__ == op) return "<<";
if(__rshift__ == op) return ">>";
if(__and__ == op) return "&";
if(__or__ == op) return "|";
if(__xor__ == op) return "^";
if(__neg__ == op) return "-";
if(__invert__ == op) return "~";
if(__matmul__ == op) return "@";
return py_name2str(op);
}
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
// [a, b]
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
if(magic) {
bool ok = py_call(magic, 2, SECOND());
if(!ok) return false;
if(self->last_retval.type != tp_NotImplementedType) return true;
}
// try reverse operation
if(rop) {
// [a, b] -> [b, a]
py_TValue tmp = *TOP();
*TOP() = *SECOND();
*SECOND() = tmp;
magic = py_tpfindmagic(SECOND()->type, rop);
if(magic) {
bool ok = py_call(magic, 2, SECOND());
if(!ok) return false;
if(self->last_retval.type != tp_NotImplementedType) return true;
}
}
// eq/ne op never fails
bool res = py_isidentical(SECOND(), TOP());
if(op == __eq__) {
py_newbool(py_retval(), res);
return true;
}
if(op == __ne__) {
py_newbool(py_retval(), !res);
return true;
}
py_Type lhs_t = rop ? TOP()->type : SECOND()->type;
py_Type rhs_t = rop ? SECOND()->type : TOP()->type;
return TypeError("unsupported operand type(s) for '%s': '%t' and '%t'",
pk_op2str(op),
lhs_t,
rhs_t);
}
bool pk_format_object(VM* self, py_Ref val, c11_sv spec) {
// format TOS via `spec` inplace
// spec: '!r:.2f', ':.2f', '.2f'
if(spec.size == 0) return py_str(val);
if(spec.data[0] == '!') {
if(c11_sv__startswith(spec, (c11_sv){"!r", 2})) {
spec.data += 2;
spec.size -= 2;
if(!py_repr(val)) return false;
py_assign(val, py_retval());
if(spec.size == 0) return true;
} else {
return ValueError("invalid conversion specifier (only !r is supported)");
}
}
assert(spec.size > 0);
if(spec.data[0] == ':') {
spec.data++;
spec.size--;
}
char type;
switch(spec.data[spec.size - 1]) {
case 'f':
case 'd':
case 's':
type = spec.data[spec.size - 1];
spec.size--; // remove last char
break;
default: type = ' '; break;
}
char pad_c = ' ';
if(strchr("0-=*#@!~", spec.data[0])) {
pad_c = spec.data[0];
spec = c11_sv__slice(spec, 1);
}
char align;
if(spec.data[0] == '^') {
align = '^';
spec = c11_sv__slice(spec, 1);
} else if(spec.data[0] == '>') {
align = '>';
spec = c11_sv__slice(spec, 1);
} else if(spec.data[0] == '<') {
align = '<';
spec = c11_sv__slice(spec, 1);
} else {
align = (py_isint(val) || py_isfloat(val)) ? '>' : '<';
}
int dot = c11_sv__index(spec, '.');
py_i64 width, precision;
if(dot >= 0) {
if(dot == 0) {
// {.2f}
width = -1;
} else {
// {10.2f}
IntParsingResult res = c11__parse_uint(c11_sv__slice2(spec, 0, dot), &width, 10);
if(res != IntParsing_SUCCESS) return ValueError("invalid format specifier");
}
IntParsingResult res = c11__parse_uint(c11_sv__slice(spec, dot + 1), &precision, 10);
if(res != IntParsing_SUCCESS) return ValueError("invalid format specifier");
} else {
// {10s}
IntParsingResult res = c11__parse_uint(spec, &width, 10);
if(res != IntParsing_SUCCESS) return ValueError("invalid format specifier");
precision = -1;
}
if(type != 'f' && dot >= 0) {
return ValueError("precision not allowed in the format specifier");
}
c11_sbuf buf;
c11_sbuf__ctor(&buf);
if(type == 'f') {
py_f64 x;
if(!py_castfloat(val, &x)) {
c11_sbuf__dtor(&buf);
return false;
}
if(precision < 0) precision = 6;
c11_sbuf__write_f64(&buf, x, precision);
} else if(type == 'd') {
if(!py_checkint(val)) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_i64(&buf, py_toint(val));
} else if(type == 's') {
if(!py_checkstr(val)) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(val));
} else {
if(!py_str(val)) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
}
c11_string* body = c11_sbuf__submit(&buf);
int length = c11_sv__u8_length(c11_string__sv(body));
c11_sbuf__ctor(&buf); // reinit sbuf
if(width != -1 && width > length) {
switch(align) {
case '>': {
c11_sbuf__write_pad(&buf, width - length, pad_c);
c11_sbuf__write_sv(&buf, c11_string__sv(body));
break;
}
case '<': {
c11_sbuf__write_sv(&buf, c11_string__sv(body));
c11_sbuf__write_pad(&buf, width - length, pad_c);
break;
}
case '^': {
int pad_left = (width - length) / 2;
int pad_right = (width - length) - pad_left;
c11_sbuf__write_pad(&buf, pad_left, pad_c);
c11_sbuf__write_sv(&buf, c11_string__sv(body));
c11_sbuf__write_pad(&buf, pad_right, pad_c);
break;
}
default: c11__unreachable();
}
} else {
c11_sbuf__write_sv(&buf, c11_string__sv(body));
}
c11_string__delete(body);
// inplace update
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
#undef DISPATCH
#undef DISPATCH_JUMP
#undef DISPATCH_JUMP_ABSOLUTE
#undef TOP
#undef SECOND
#undef THIRD
#undef FOURTH
#undef STACK_SHRINK
#undef STACK_GROW
#undef PUSH
#undef POP
#undef POPX
#undef SP
#undef INSERT_THIRD
#undef vectorcall_opcall
#undef RESET_CO_CACHE
// src/interpreter\dll.c
#if PK_IS_DESKTOP_PLATFORM && PK_ENABLE_OS
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#else
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#endif
typedef bool (*py_module_initialize_t)() PY_RAISE PY_RETURN;
int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN {
const char* f_init_name = "py_module_initialize";
#ifdef _WIN32
void* dll = LoadLibraryA(path);
if(dll == NULL) return 0;
py_module_initialize_t f_init = (py_module_initialize_t)GetProcAddress(dll, f_init_name);
#else
void* dll = NULL;
// On Linux, dlopen doesn't automatically add .so suffix like Windows does with .dll
// Also, CMake typically generates libXxx.so instead of Xxx.so
// Try: path.so, libpath.so, then the original path
char* path_with_so = NULL;
char* path_with_lib = NULL;
size_t path_len = strlen(path);
// Try path.so
path_with_so = py_malloc(path_len + 4); // .so + null terminator
if(path_with_so != NULL) {
strcpy(path_with_so, path);
strcat(path_with_so, ".so");
dll = dlopen(path_with_so, RTLD_LAZY);
py_free(path_with_so);
}
// Try libpath.so if path.so didn't work
if(dll == NULL) {
path_with_lib = py_malloc(path_len + 7); // lib + .so + null terminator
if(path_with_lib != NULL) {
strcpy(path_with_lib, "lib");
strcat(path_with_lib, path);
strcat(path_with_lib, ".so");
dll = dlopen(path_with_lib, RTLD_LAZY);
py_free(path_with_lib);
}
}
// Fallback to original path
if(dll == NULL) {
dll = dlopen(path, RTLD_LAZY);
}
if(dll == NULL) return 0;
py_module_initialize_t f_init = (py_module_initialize_t)dlsym(dll, f_init_name);
#endif
if(f_init == NULL) return 0;
bool success = f_init();
if(!success) return -1;
return 1;
}
#else
int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN {
return 0;
}
#endif
// src/interpreter\frame.c
#include <stdbool.h>
#include <assert.h>
void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) {
py_StackRef dict = py_pushtmp();
py_newdict(dict);
c11__foreach(c11_smallmap_n2d_KV, &co->varnames_inv, entry) {
py_TValue* value = &locals[entry->value];
if(!py_isnil(value)) {
bool ok = py_dict_setitem(dict, py_name2ref(entry->key), value);
assert(ok);
(void)ok;
}
}
py_assign(py_retval(), dict);
py_pop();
}
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
NameDict* dict = NameDict__new(PK_INST_ATTR_LOAD_FACTOR);
c11__foreach(c11_smallmap_n2d_KV, &co->varnames_inv, entry) {
py_Ref val = &locals[entry->value];
if(!py_isnil(val)) NameDict__set(dict, entry->key, val);
}
return dict;
}
py_Frame* Frame__new(const CodeObject* co,
py_StackRef p0,
py_GlobalRef module,
py_Ref globals,
py_Ref locals,
bool is_locals_special) {
assert(module->type == tp_module);
assert(globals->type == tp_module || globals->type == tp_dict);
if(is_locals_special) {
assert(locals->type == tp_nil || locals->type == tp_locals || locals->type == tp_dict);
}
py_Frame* self = FixedMemoryPool__alloc(&pk_current_vm->pool_frame);
self->f_back = NULL;
self->co = co;
self->p0 = p0;
self->module = module;
self->globals = globals;
self->locals = locals;
self->is_locals_special = is_locals_special;
self->ip = -1;
c11_vector__ctor(&self->exc_stack, sizeof(FrameExcInfo));
return self;
}
void Frame__delete(py_Frame* self) {
c11_vector__dtor(&self->exc_stack);
FixedMemoryPool__dealloc(&pk_current_vm->pool_frame, self);
}
int Frame__goto_exception_handler(py_Frame* self, ValueStack* value_stack, py_Ref exc) {
FrameExcInfo* p = self->exc_stack.data;
for(int i = self->exc_stack.length - 1; i >= 0; i--) {
if(py_isnil(&p[i].exc)) {
value_stack->sp = (self->p0 + p[i].offset); // unwind the stack
return c11__at(CodeBlock, &self->co->blocks, p[i].iblock)->end;
} else {
self->exc_stack.length--;
}
}
return -1;
}
void Frame__begin_try(py_Frame* self, py_TValue* sp) {
int iblock = Frame__iblock(self);
assert(iblock >= 0);
FrameExcInfo* info = c11_vector__emplace(&self->exc_stack);
info->iblock = iblock;
info->offset = (int)(sp - self->p0);
py_newnil(&info->exc);
}
FrameExcInfo* Frame__top_exc_info(py_Frame* self) {
if(self->exc_stack.length == 0) return NULL;
return &c11_vector__back(FrameExcInfo, &self->exc_stack);
}
void Frame__gc_mark(py_Frame* self, c11_vector* p_stack) {
pk__mark_value(self->globals);
if(self->is_locals_special) pk__mark_value(self->locals);
CodeObject__gc_mark(self->co, p_stack);
c11__foreach(FrameExcInfo, &self->exc_stack, info) { pk__mark_value(&info->exc); }
}
int Frame__lineno(const py_Frame* self) {
int ip = self->ip;
if(ip >= 0) {
BytecodeEx* ex = c11__at(BytecodeEx, &self->co->codes_ex, ip);
return ex->lineno;
}
if(!self->is_locals_special) return self->co->start_line;
return 0;
}
int Frame__iblock(const py_Frame* self) {
int ip = self->ip;
if(ip < 0) return -1;
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
}
int Frame__getglobal(py_Frame* self, py_Name name) {
if(self->globals->type == tp_module) {
py_ItemRef item = py_getdict(self->globals, name);
if(item != NULL) {
py_assign(py_retval(), item);
return 1;
}
return 0;
} else {
return py_dict_getitem(self->globals, py_name2ref(name));
}
}
bool Frame__setglobal(py_Frame* self, py_Name name, py_TValue* val) {
if(self->globals->type == tp_module) {
py_setdict(self->globals, name, val);
return true;
} else {
return py_dict_setitem(self->globals, py_name2ref(name), val);
}
}
int Frame__delglobal(py_Frame* self, py_Name name) {
if(self->globals->type == tp_module) {
bool found = py_deldict(self->globals, name);
return found ? 1 : 0;
} else {
return py_dict_delitem(self->globals, py_name2ref(name));
}
}
py_StackRef Frame__getlocal_noproxy(py_Frame* self, py_Name name) {
assert(!self->is_locals_special);
int index = c11_smallmap_n2d__get(&self->co->varnames_inv, name, -1);
if(index == -1) return NULL;
return &self->locals[index];
}
py_Ref Frame__getclosure(py_Frame* self, py_Name name) {
if(self->is_locals_special) return NULL;
assert(self->p0->type == tp_function);
Function* ud = py_touserdata(self->p0);
if(ud->closure == NULL) return NULL;
return NameDict__try_get(ud->closure, name);
}
SourceLocation Frame__source_location(py_Frame* self) {
SourceLocation loc;
loc.lineno = Frame__lineno(self);
loc.src = self->co->src;
return loc;
}
// src/interpreter\generator.c
#include <stdbool.h>
#include <assert.h>
void pk_newgenerator(py_Ref out, py_Frame* frame, py_TValue* begin, py_TValue* end) {
Generator* ud = py_newobject(out, tp_generator, 1, sizeof(Generator));
ud->frame = frame;
ud->state = 0;
py_Ref tmp = py_getslot(out, 0);
py_newlist(tmp);
for(py_TValue* p = begin; p != end; p++) {
py_list_append(tmp, p);
}
}
void Generator__dtor(Generator* ud) {
if(ud->frame) Frame__delete(ud->frame);
}
bool generator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Generator* ud = py_touserdata(argv);
py_StackRef p0 = py_peek(0);
VM* vm = pk_current_vm;
if(ud->state == 2) return StopIteration();
// reset frame->p0
assert(!ud->frame->is_locals_special);
int locals_offset = ud->frame->locals - ud->frame->p0;
ud->frame->p0 = py_peek(0);
ud->frame->locals = ud->frame->p0 + locals_offset;
// restore the context
py_Ref backup = py_getslot(argv, 0);
int length = py_list_len(backup);
py_TValue* p = py_list_data(backup);
for(int i = 0; i < length; i++)
py_push(&p[i]);
py_list_clear(backup);
// push frame
VM__push_frame(vm, ud->frame);
ud->frame = NULL;
FrameResult res = VM__run_top_frame(vm);
if(res == RES_ERROR) {
ud->state = 2; // end this generator immediately on error
if(py_matchexc(tp_StopIteration)) {
py_clearexc(p0);
return true;
}
return false;
}
if(res == RES_YIELD) {
// backup the context
ud->frame = vm->top_frame;
for(py_StackRef p = ud->frame->p0; p != vm->stack.sp; p++) {
py_list_append(backup, p);
}
vm->stack.sp = ud->frame->p0;
vm->top_frame = vm->top_frame->f_back;
vm->recursion_depth--;
ud->state = 1;
return true;
} else {
assert(res == RES_RETURN);
ud->state = 2;
// raise StopIteration(<retval>)
bool ok = py_tpcall(tp_StopIteration, 1, py_retval());
if(!ok) return false;
return py_raise(py_retval());
}
}
py_Type pk_generator__register() {
py_Type type = pk_newtype("generator", tp_object, NULL, (py_Dtor)Generator__dtor, false, true);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, generator__next__);
return type;
}
// src/interpreter\heap.c
#include <assert.h>
static uint8_t encode_size_8b(int size, int* out_size) {
int bit_length = c11__bit_length(size);
int min_val = 1 << (bit_length - 1);
int gap = min_val;
float ratio = (float)(size - min_val) / gap;
int ratio_3bit = (int)(ratio * 7.999f);
*out_size = min_val + (int)(gap * ((float)ratio_3bit / 7.999f));
return (uint8_t)((bit_length << 3) | ratio_3bit);
}
static int decode_size_8b(uint8_t byte) {
int bit_length = byte >> 3;
int ratio_3bit = byte & 0x07;
int min_val = 1 << (bit_length - 1);
int gap = min_val;
float ratio = (float)ratio_3bit / 7.999f;
return min_val + (int)(gap * ratio);
}
void ManagedHeap__ctor(ManagedHeap* self) {
MultiPool__ctor(&self->small_objects);
c11_vector__ctor(&self->large_objects, sizeof(PyObject*));
c11_vector__ctor(&self->gc_roots, sizeof(PyObject*));
self->large_total_size = 0;
for(int i = 0; i < c11__count_array(self->freed_ma); i++) {
self->freed_ma[i] = PK_GC_MIN_THRESHOLD;
}
self->gc_threshold = PK_GC_MIN_THRESHOLD;
self->gc_counter = 0;
self->gc_enabled = true;
self->debug_callback = *py_None();
}
void ManagedHeap__dtor(ManagedHeap* self) {
// small_objects
MultiPool__dtor(&self->small_objects);
// large_objects
for(int i = 0; i < self->large_objects.length; i++) {
PyObject* obj = c11__getitem(PyObject*, &self->large_objects, i);
PyObject__dtor(obj);
PK_FREE(obj);
}
c11_vector__dtor(&self->large_objects);
c11_vector__dtor(&self->gc_roots);
}
static void ManagedHeap__fire_debug_callback_start(ManagedHeap* self) {
py_push(&self->debug_callback);
py_pushnil();
py_newstr(py_pushtmp(), "start");
py_newstr(py_pushtmp(), "");
bool ok = py_vectorcall(2, 0);
if(!ok) {
char* msg = py_formatexc();
c11__abort("gc_debug_callback error!!\n%s", msg);
}
}
static void ManagedHeap__fire_debug_callback_stop(ManagedHeap* self,
ManagedHeapSwpetInfo* out_info) {
assert(out_info != NULL);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
const int64_t NANOS_PER_MS = 1000000000 / 1000;
const char* DIVIDER = "------------------------------------------------------------\n";
int64_t mark_ms = (out_info->mark_end_ns - out_info->start_ns) / NANOS_PER_MS;
int64_t swpet_ms = (out_info->swpet_end_ns - out_info->mark_end_ns) / NANOS_PER_MS;
c11_sbuf__write_cstr(&buf, DIVIDER);
pk_sprintf(&buf, "start: %f\n", out_info->start_ns / 1e9);
pk_sprintf(&buf, "mark_ms: %i\n", (py_i64)mark_ms);
pk_sprintf(&buf, "swpet_ms: %i\n", (py_i64)swpet_ms);
pk_sprintf(&buf, "total_ms: %i\n", (py_i64)(mark_ms + swpet_ms));
c11_sbuf__write_cstr(&buf, DIVIDER);
pk_sprintf(&buf, "types_length: %d\n", out_info->types_length);
pk_sprintf(&buf, "small_freed: %d\n", out_info->small_freed);
pk_sprintf(&buf, "large_freed: %d\n", out_info->large_freed);
c11_sbuf__write_cstr(&buf, DIVIDER);
if(out_info->small_freed != 0 || out_info->large_freed != 0) {
char line_buf[256];
for(int i = 0; i < out_info->types_length; i++) {
const char* type_name = py_tpname(i);
int s_freed = out_info->small_types[i];
int l_freed = out_info->large_types[i];
if(s_freed == 0 && l_freed == 0) continue;
snprintf(line_buf,
sizeof(line_buf),
"[%-24s] small: %6d large: %6d\n",
type_name,
s_freed,
l_freed);
c11_sbuf__write_cstr(&buf, line_buf);
}
c11_sbuf__write_cstr(&buf, DIVIDER);
}
pk_sprintf(&buf, "auto_thres.before: %d\n", out_info->auto_thres.before);
pk_sprintf(&buf, "auto_thres.after: %d\n", out_info->auto_thres.after);
pk_sprintf(&buf, "auto_thres.upper: %d\n", out_info->auto_thres.upper);
pk_sprintf(&buf, "auto_thres.lower: %d\n", out_info->auto_thres.lower);
pk_sprintf(&buf, "auto_thres.avg_freed: %d\n", out_info->auto_thres.avg_freed);
pk_sprintf(&buf, "auto_thres.free_ratio: %f\n", out_info->auto_thres.free_ratio);
c11_sbuf__write_cstr(&buf, DIVIDER);
py_push(&self->debug_callback);
py_pushnil();
py_newstr(py_pushtmp(), "stop");
py_StackRef arg = py_pushtmp();
c11_sbuf__py_submit(&buf, arg);
bool ok = py_vectorcall(2, 0);
if(!ok) {
char* msg = py_formatexc();
c11__abort("gc_debug_callback error!!\n%s", msg);
}
}
int ManagedHeap__collect_hint(ManagedHeap* self) {
if(self->gc_counter < self->gc_threshold) return 0;
self->gc_counter = 0;
ManagedHeapSwpetInfo* out_info = NULL;
if(!py_isnone(&self->debug_callback)) {
out_info = ManagedHeapSwpetInfo__new();
ManagedHeap__fire_debug_callback_start(self);
}
ManagedHeap__mark(self);
if(out_info) out_info->mark_end_ns = time_ns();
int freed = ManagedHeap__sweep(self, out_info);
if(out_info) out_info->swpet_end_ns = time_ns();
// adjust `gc_threshold` based on `freed_ma`
self->freed_ma[0] = self->freed_ma[1];
self->freed_ma[1] = self->freed_ma[2];
self->freed_ma[2] = freed;
int avg_freed = (self->freed_ma[0] + self->freed_ma[1] + self->freed_ma[2]) / 3;
const int upper = PK_GC_MIN_THRESHOLD * 8;
const int lower = PK_GC_MIN_THRESHOLD / 2;
float free_ratio = (float)avg_freed / self->gc_threshold;
int new_threshold = self->gc_threshold * (1.5f / free_ratio);
if(out_info) {
out_info->auto_thres.before = self->gc_threshold;
out_info->auto_thres.after = new_threshold;
out_info->auto_thres.upper = upper;
out_info->auto_thres.lower = lower;
out_info->auto_thres.avg_freed = avg_freed;
out_info->auto_thres.free_ratio = free_ratio;
}
self->gc_threshold = c11__min(c11__max(new_threshold, lower), upper);
if(!py_isnone(&self->debug_callback)) {
ManagedHeap__fire_debug_callback_stop(self, out_info);
ManagedHeapSwpetInfo__delete(out_info);
}
return freed;
}
int ManagedHeap__collect(ManagedHeap* self) {
self->gc_counter = 0;
ManagedHeapSwpetInfo* out_info = NULL;
if(!py_isnone(&self->debug_callback)) {
out_info = ManagedHeapSwpetInfo__new();
ManagedHeap__fire_debug_callback_start(self);
}
ManagedHeap__mark(self);
if(out_info) out_info->mark_end_ns = time_ns();
int freed = ManagedHeap__sweep(self, out_info);
if(out_info) out_info->swpet_end_ns = time_ns();
if(out_info) {
out_info->auto_thres.before = self->gc_threshold;
out_info->auto_thres.after = self->gc_threshold;
}
if(!py_isnone(&self->debug_callback)) {
ManagedHeap__fire_debug_callback_stop(self, out_info);
ManagedHeapSwpetInfo__delete(out_info);
}
return freed;
}
int ManagedHeap__sweep(ManagedHeap* self, ManagedHeapSwpetInfo* out_info) {
// small_objects
int small_freed =
MultiPool__sweep_dealloc(&self->small_objects, out_info ? out_info->small_types : NULL);
// large_objects
int large_living_count = 0;
for(int i = 0; i < self->large_objects.length; i++) {
PyObject* obj = c11__getitem(PyObject*, &self->large_objects, i);
if(obj->gc_marked) {
obj->gc_marked = false;
c11__setitem(PyObject*, &self->large_objects, large_living_count, obj);
large_living_count++;
} else {
if(out_info) out_info->large_types[obj->type]++;
self->large_total_size -= decode_size_8b(obj->size_8b);
PyObject__dtor(obj);
PK_FREE(obj);
}
}
// shrink `self->large_objects`
int large_freed = self->large_objects.length - large_living_count;
self->large_objects.length = large_living_count;
if(out_info) {
out_info->small_freed = small_freed;
out_info->large_freed = large_freed;
}
return small_freed + large_freed;
}
PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize) {
assert(slots >= 0 || slots == -1);
// header + slots + udsize
int size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + udsize;
PyObject* obj = MultiPool__alloc(&self->small_objects, size);
uint8_t size_8b = 0;
if(obj == NULL) {
obj = PK_MALLOC(size);
int quantized_size;
size_8b = encode_size_8b(size, &quantized_size);
self->large_total_size += quantized_size;
c11_vector__push(PyObject*, &self->large_objects, obj);
}
obj->type = type;
obj->size_8b = size_8b;
obj->gc_marked = false;
obj->slots = slots;
// initialize slots or dict
if(slots >= 0) {
memset(obj->flex, 0, slots * sizeof(py_TValue));
} else {
float load_factor = (type == tp_type || type == tp_module) ? PK_TYPE_ATTR_LOAD_FACTOR
: PK_INST_ATTR_LOAD_FACTOR;
NameDict__ctor((void*)obj->flex, load_factor);
}
self->gc_counter++;
return obj;
}
// src/interpreter\line_profiler.c
#include <assert.h>
void LineProfiler__ctor(LineProfiler* self) {
c11_smallmap_p2i__ctor(&self->records);
c11_vector__ctor(&self->frame_records, sizeof(FrameRecord));
self->enabled = false;
}
void LineProfiler__dtor(LineProfiler* self) {
for(int i = 0; i < self->records.length; i++) {
c11_smallmap_p2i_KV kv = c11__getitem(c11_smallmap_p2i_KV, &self->records, i);
SourceData_ src = (SourceData_)kv.key;
PK_DECREF(src);
PK_FREE((void*)kv.value);
}
c11_smallmap_p2i__dtor(&self->records);
c11_vector__dtor(&self->frame_records);
}
LineRecord* LineProfiler__get_record(LineProfiler* self, SourceLocation loc) {
LineRecord* lines = (LineRecord*)c11_smallmap_p2i__get(&self->records, loc.src, 0);
if(lines == NULL) {
int max_lineno = loc.src->line_starts.length;
lines = PK_MALLOC(sizeof(LineRecord) * (max_lineno + 1));
memset(lines, 0, sizeof(LineRecord) * (max_lineno + 1));
c11_smallmap_p2i__set(&self->records, loc.src, (py_i64)lines);
PK_INCREF(loc.src);
}
return &lines[loc.lineno];
}
void LineProfiler__begin(LineProfiler* self) {
assert(!self->enabled);
self->enabled = true;
}
static void LineProfiler__increment_now(LineProfiler* self, clock_t now, LineRecord* curr_line) {
FrameRecord* top_frame_record = &c11_vector__back(FrameRecord, &self->frame_records);
if(!top_frame_record->is_lambda) {
LineRecord* prev_line = top_frame_record->prev_line;
clock_t delta = now - top_frame_record->prev_time;
top_frame_record->prev_time = now;
prev_line->hits++;
prev_line->time += delta;
// printf(" ==> increment_now: delta: %ld, hits: %lld\n", delta, prev_line->hits);
}
top_frame_record->prev_line = curr_line;
}
void LineProfiler__tracefunc_internal(LineProfiler* self,
py_Frame* frame,
enum py_TraceEvent event) {
assert(self->enabled);
clock_t now = clock();
// SourceLocation curr_loc = Frame__source_location(frame);
// printf("==> frame: %p:%d, event: %d, now: %ld\n", frame, curr_loc.lineno, event, now);
SourceLocation curr_loc = Frame__source_location(frame);
LineRecord* curr_line = LineProfiler__get_record(self, curr_loc);
if(event == TRACE_EVENT_LINE) {
LineProfiler__increment_now(self, now, curr_line);
} else {
if(event == TRACE_EVENT_PUSH) {
FrameRecord f_record = {.frame = frame,
.prev_time = now,
.prev_line = curr_line,
.is_lambda = false};
if(!frame->is_locals_special && py_istype(frame->p0, tp_function)) {
Function* fn = py_touserdata(frame->p0);
c11_string* fn_name = fn->decl->code.name;
f_record.is_lambda = fn_name->size > 0 && fn_name->data[0] == '<';
}
c11_vector__push(FrameRecord, &self->frame_records, f_record);
} else if(event == TRACE_EVENT_POP) {
LineProfiler__increment_now(self, now, NULL);
assert(self->frame_records.length > 0);
c11_vector__pop(&self->frame_records);
}
}
}
void LineProfiler__end(LineProfiler* self) {
assert(self->enabled);
if(self->frame_records.length > 0) LineProfiler__increment_now(self, clock(), NULL);
self->enabled = false;
}
void LineProfiler__reset(LineProfiler* self) {
LineProfiler__dtor(self);
LineProfiler__ctor(self);
}
c11_string* LineProfiler__get_report(LineProfiler* self) {
c11_sbuf sbuf;
c11_sbuf__ctor(&sbuf);
c11_sbuf__write_char(&sbuf, '{');
c11_sbuf__write_cstr(&sbuf, "\"CLOCKS_PER_SEC\": ");
c11_sbuf__write_i64(&sbuf, CLOCKS_PER_SEC);
c11_sbuf__write_cstr(&sbuf, ", \"records\": ");
c11_sbuf__write_char(&sbuf, '{');
for(int i = 0; i < self->records.length; i++) {
c11_smallmap_p2i_KV kv = c11__getitem(c11_smallmap_p2i_KV, &self->records, i);
SourceData_ src = (SourceData_)kv.key;
int line_record_length = src->line_starts.length + 1;
c11_sv src_name = c11_string__sv(src->filename);
c11_sbuf__write_quoted(&sbuf, src_name, '"');
c11_sbuf__write_cstr(&sbuf, ": [");
LineRecord* lines = (LineRecord*)kv.value;
bool is_first = true;
for(int j = 1; j < line_record_length; j++) {
// [<j>, <hits>, <time>]
if(lines[j].hits == 0 && lines[j].time == 0) continue;
if(!is_first) c11_sbuf__write_cstr(&sbuf, ", ");
c11_sbuf__write_char(&sbuf, '[');
c11_sbuf__write_int(&sbuf, j);
c11_sbuf__write_cstr(&sbuf, ", ");
c11_sbuf__write_i64(&sbuf, lines[j].hits);
c11_sbuf__write_cstr(&sbuf, ", ");
c11_sbuf__write_i64(&sbuf, lines[j].time);
c11_sbuf__write_char(&sbuf, ']');
is_first = false;
}
c11_sbuf__write_cstr(&sbuf, "]");
if(i < self->records.length - 1) c11_sbuf__write_cstr(&sbuf, ", ");
}
c11_sbuf__write_char(&sbuf, '}');
c11_sbuf__write_char(&sbuf, '}');
return c11_sbuf__submit(&sbuf);
}
// src/interpreter\objectpool.c
#include <assert.h>
#include <stdbool.h>
#include <string.h>
static PoolArena* PoolArena__new(int block_size) {
assert(kPoolArenaSize % block_size == 0);
int block_count = kPoolArenaSize / block_size;
PoolArena* self = PK_MALLOC(sizeof(PoolArena) + sizeof(int) * block_count);
self->block_size = block_size;
self->block_count = block_count;
self->unused_length = block_count;
for(int i = 0; i < block_count; i++) {
self->unused[i] = i;
}
memset(self->data, 0, kPoolArenaSize);
return self;
}
static void* PoolArena__alloc(PoolArena* self) {
assert(self->unused_length > 0);
int index = self->unused[self->unused_length - 1];
self->unused_length--;
return self->data + index * self->block_size;
}
static int PoolArena__sweep_dealloc(PoolArena* self, int* out_types) {
int unused_length_before = self->unused_length;
self->unused_length = 0;
for(int i = 0; i < self->block_count; i++) {
PyObject* obj = (PyObject*)(self->data + i * self->block_size);
if(obj->type == 0) {
// free slot
self->unused[self->unused_length] = i;
self->unused_length++;
} else {
if(!obj->gc_marked) {
// not marked, need to free
if(out_types) out_types[obj->type]++;
PyObject__dtor(obj);
obj->type = 0;
self->unused[self->unused_length] = i;
self->unused_length++;
} else {
// marked, clear mark
obj->gc_marked = false;
}
}
}
return self->unused_length - unused_length_before;
}
static void Pool__ctor(Pool* self, int block_size) {
c11_vector__ctor(&self->arenas, sizeof(PoolArena*));
self->available_index = 0;
self->block_size = block_size;
}
static void Pool__dtor(Pool* self) {
for(int i = 0; i < self->arenas.length; i++) {
PoolArena* arena = c11__getitem(PoolArena*, &self->arenas, i);
for(int i = 0; i < arena->block_count; i++) {
PyObject* obj = (PyObject*)(arena->data + i * self->block_size);
if(obj->type != 0) PyObject__dtor(obj);
}
PK_FREE(arena);
}
c11_vector__dtor(&self->arenas);
}
static void* Pool__alloc(Pool* self) {
PoolArena* arena;
if(self->available_index < self->arenas.length) {
arena = c11__getitem(PoolArena*, &self->arenas, self->available_index);
} else {
arena = PoolArena__new(self->block_size);
c11_vector__push(PoolArena*, &self->arenas, arena);
self->available_index = self->arenas.length - 1;
}
void* ptr = PoolArena__alloc(arena);
if(arena->unused_length == 0) self->available_index++;
return ptr;
}
static int Pool__sweep_dealloc(Pool* self, int* out_types) {
PoolArena** p = self->arenas.data;
int freed = 0;
for(int i = 0; i < self->arenas.length; i++) {
freed += PoolArena__sweep_dealloc(p[i], out_types);
}
// move arenas with `unused_length == 0` to the front
int j = 0;
for(int i = 0; i < self->arenas.length; i++) {
if(p[i]->unused_length == 0) {
PoolArena* tmp = p[i];
p[i] = p[j];
p[j] = tmp;
j++;
}
}
// move arenas with `unused_length < block_count` to the front
int k = j;
for(int i = j; i < self->arenas.length; i++) {
if(p[i]->unused_length < p[i]->block_count) {
PoolArena* tmp = p[i];
p[i] = p[k];
p[k] = tmp;
k++;
}
}
// free excess free arenas
int free_quota = self->arenas.length / 2;
int min_length = c11__max(free_quota, j + 1);
while(self->arenas.length > min_length) {
PoolArena* back_arena = c11_vector__back(PoolArena*, &self->arenas);
if(back_arena->unused_length == back_arena->block_count) {
PK_FREE(back_arena);
c11_vector__pop(&self->arenas);
} else {
break;
}
}
// [[0, 0, 0, 0, 0, 1], 1, 1, 1, 2, 2]
// ^j=5 ^k
self->available_index = j;
return freed;
}
void* MultiPool__alloc(MultiPool* self, int size) {
assert(size > 0);
int index = (size - 1) >> 5;
if(index < kMultiPoolCount) {
Pool* pool = &self->pools[index];
return Pool__alloc(pool);
}
return NULL;
}
int MultiPool__sweep_dealloc(MultiPool* self, int* out_types) {
int freed = 0;
for(int i = 0; i < kMultiPoolCount; i++) {
Pool* item = &self->pools[i];
freed += Pool__sweep_dealloc(item, out_types);
}
return freed;
}
void MultiPool__ctor(MultiPool* self) {
for(int i = 0; i < kMultiPoolCount; i++) {
Pool__ctor(&self->pools[i], 32 * (i + 1));
}
}
void MultiPool__dtor(MultiPool* self) {
for(int i = 0; i < kMultiPoolCount; i++) {
Pool__dtor(&self->pools[i]);
}
}
size_t MultiPool__total_allocated_bytes(MultiPool* self) {
size_t total = 0;
for(int i = 0; i < kMultiPoolCount; i++) {
Pool* item = &self->pools[i];
total += (size_t)item->arenas.length * kPoolArenaSize;
}
return total;
}
c11_string* MultiPool__summary(MultiPool* self) {
c11_sbuf sbuf;
c11_sbuf__ctor(&sbuf);
int arena_count = 0;
char buf[256];
for(int i = 0; i < kMultiPoolCount; i++) {
Pool* item = &self->pools[i];
arena_count += item->arenas.length;
int total_bytes = item->arenas.length * kPoolArenaSize;
int used_bytes = 0;
for(int j = 0; j < item->arenas.length; j++) {
PoolArena* arena = c11__getitem(PoolArena*, &item->arenas, j);
used_bytes += (arena->block_count - arena->unused_length) * arena->block_size;
}
float used_pct = (float)used_bytes / total_bytes * 100;
if(total_bytes == 0) used_pct = 0.0f;
snprintf(buf,
sizeof(buf),
"Pool %3d: len(arenas)=%d (%d full), size=%d/%d (%.1f%% used)\n",
item->block_size,
item->arenas.length,
item->available_index,
used_bytes,
total_bytes,
used_pct);
c11_sbuf__write_cstr(&sbuf, buf);
}
long long total_size = arena_count * kPoolArenaSize;
double total_size_mb = (long long)(total_size / 1024) / 1024.0;
snprintf(buf, sizeof(buf), "Total: %.2f MB\n", total_size_mb);
c11_sbuf__write_cstr(&sbuf, buf);
return c11_sbuf__submit(&sbuf);
}
// src/interpreter\py_compile.c
#include <errno.h>
bool py_compilefile(const char* src_path, const char* dst_path) {
// read
FILE* fp = fopen(src_path, "rb");
if(fp == NULL) {
const char* msg = strerror(errno);
return OSError("[Errno %d] %s: '%s'", errno, msg, src_path);
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* buffer = PK_MALLOC(size + 1);
size = fread(buffer, 1, size, fp);
buffer[size] = 0;
fclose(fp);
// compile
bool ok = py_compile(buffer, src_path, EXEC_MODE, false);
PK_FREE(buffer);
if(!ok) return false;
// dump
py_assign(py_pushtmp(), py_retval());
int bc_size;
void* bc_data = CodeObject__dumps(py_touserdata(py_peek(-1)), &bc_size);
py_pop();
// write
fp = fopen(dst_path, "wb");
if(fp == NULL) {
PK_FREE(bc_data);
const char* msg = strerror(errno);
return OSError("[Errno %d] %s: '%s'", errno, msg, dst_path);
}
fwrite(bc_data, 1, bc_size, fp);
fclose(fp);
PK_FREE(bc_data);
return true;
}
// src/interpreter\typeinfo.c
#include <assert.h>
py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name) {
assert(ti != NULL);
do {
py_Ref res = py_getdict(&ti->self, name);
if(res) return res;
ti = ti->base_ti;
} while(ti);
return NULL;
}
PK_INLINE py_TypeInfo* pk_typeinfo(py_Type type) {
#ifndef NDEBUG
int length = pk_current_vm->types.length;
if(type <= 0 || type >= length) {
c11__abort("type index %d is out of bounds (0, %d)", type, length);
}
#endif
return c11__getitem(TypePointer, &pk_current_vm->types, type).ti;
}
static void py_TypeInfo__common_init(py_Name name,
py_Type base,
py_Type index,
const py_GlobalRef module,
void (*dtor)(void*),
bool is_python,
bool is_final,
py_TypeInfo* self,
py_TValue* typeobject) {
py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL;
if(base_ti && base_ti->is_final) {
c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name));
}
self->name = name;
self->index = index;
self->base = base;
self->base_ti = base_ti;
py_assign(&self->self, typeobject);
self->module = module ? module : py_NIL();
if(!dtor && base) dtor = base_ti->dtor;
self->is_python = is_python;
self->is_final = is_final;
self->getattribute = NULL;
self->setattribute = NULL;
self->delattribute = NULL;
self->getunboundmethod = NULL;
self->annotations = *py_NIL();
self->dtor = dtor;
self->on_end_subclass = NULL;
}
py_Type pk_newtype(const char* name,
py_Type base,
const py_GlobalRef module,
void (*dtor)(void*),
bool is_python,
bool is_final) {
py_Type index = pk_current_vm->types.length;
py_TypeInfo* self = py_newobject(py_retval(), tp_type, -1, sizeof(py_TypeInfo));
py_TypeInfo__common_init(py_name(name),
base,
index,
module,
dtor,
is_python,
is_final,
self,
py_retval());
TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types);
pointer->ti = self;
pointer->dtor = self->dtor;
return index;
}
py_Type pk_newtypewithmode(py_Name name,
py_Type base,
const py_GlobalRef module,
void (*dtor)(void*),
bool is_python,
bool is_final,
enum py_CompileMode mode) {
if(mode == RELOAD_MODE && module != NULL) {
py_ItemRef old_class = py_getdict(module, name);
if(old_class != NULL && py_istype(old_class, tp_type)) {
#ifndef NDEBUG
const char* name_cstr = py_name2str(name);
(void)name_cstr; // avoid unused warning
#endif
py_cleardict(old_class);
py_TypeInfo* self = py_touserdata(old_class);
py_Type index = self->index;
py_TypeInfo__common_init(name,
base,
index,
module,
dtor,
is_python,
is_final,
self,
&self->self);
TypePointer* pointer = c11__at(TypePointer, &pk_current_vm->types, index);
pointer->ti = self;
pointer->dtor = self->dtor;
return index;
}
}
return pk_newtype(py_name2str(name), base, module, dtor, is_python, is_final);
}
// src/interpreter\vm.c
#include <stdbool.h>
#include <assert.h>
static char* pk_default_importfile(const char* path, int* data_size) {
#if PK_ENABLE_OS
FILE* f = fopen(path, "rb");
if(f == NULL) return NULL;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
char* buffer = PK_MALLOC(size + 1);
size = fread(buffer, 1, size, f);
buffer[size] = 0;
fclose(f);
if(data_size) *data_size = (int)size;
return buffer;
#else
return NULL;
#endif
}
static void pk_default_print(const char* data) { printf("%s", data); }
static void pk_default_flush() { fflush(stdout); }
static int pk_default_getchr() { return getchar(); }
void py_profiler_begin() {
LineProfiler* lp = &pk_current_vm->line_profiler;
TraceInfo* trace_info = &pk_current_vm->trace_info;
if(trace_info->func == NULL) py_sys_settrace(LineProfiler_tracefunc, true);
c11__rtassert(trace_info->func == LineProfiler_tracefunc);
LineProfiler__begin(lp);
}
void py_profiler_end() {
LineProfiler* lp = &pk_current_vm->line_profiler;
LineProfiler__end(lp);
}
void py_profiler_reset() {
LineProfiler* lp = &pk_current_vm->line_profiler;
LineProfiler__reset(lp);
}
char* py_profiler_report() {
LineProfiler* lp = &pk_current_vm->line_profiler;
if(lp->enabled) LineProfiler__end(lp);
c11_string* s = LineProfiler__get_report(lp);
char* s_dup = c11_strdup(s->data);
c11_string__delete(s);
return s_dup;
}
void LineProfiler_tracefunc(py_Frame* frame, enum py_TraceEvent event) {
LineProfiler* lp = &pk_current_vm->line_profiler;
if(lp->enabled) LineProfiler__tracefunc_internal(lp, frame, event);
}
static int BinTree__cmp_cstr(void* lhs, void* rhs) {
const char* l = (const char*)lhs;
const char* r = (const char*)rhs;
return strcmp(l, r);
}
void VM__ctor(VM* self) {
self->top_frame = NULL;
const static BinTreeConfig modules_config = {
.f_cmp = BinTree__cmp_cstr,
.need_free_key = false,
};
BinTree__ctor(&self->modules, "", py_NIL(), &modules_config);
c11_vector__ctor(&self->types, sizeof(TypePointer));
self->builtins = NULL;
self->main = NULL;
self->callbacks.importfile = pk_default_importfile;
self->callbacks.lazyimport = NULL;
self->callbacks.print = pk_default_print;
self->callbacks.flush = pk_default_flush;
self->callbacks.getchr = pk_default_getchr;
self->last_retval = *py_NIL();
self->unhandled_exc = *py_NIL();
self->recursion_depth = 0;
self->max_recursion_depth = 1000;
memset(self->reg, 0, sizeof(self->reg));
self->ctx = NULL;
self->curr_class = NULL;
self->curr_function = NULL;
memset(&self->trace_info, 0, sizeof(TraceInfo));
memset(&self->watchdog_info, 0, sizeof(WatchdogInfo));
LineProfiler__ctor(&self->line_profiler);
FixedMemoryPool__ctor(&self->pool_frame, sizeof(py_Frame), 32);
ManagedHeap__ctor(&self->heap);
self->stack.sp = self->stack.begin;
self->stack.end = self->stack.begin + PK_VM_STACK_SIZE;
CachedNames__ctor(&self->cached_names);
/* Init Builtin Types */
// 0: unused
TypePointer* placeholder = c11_vector__emplace(&self->types);
placeholder->ti = NULL;
placeholder->dtor = NULL;
#define validate(t, expr) \
if(t != (expr)) abort()
validate(tp_object, pk_newtype("object", tp_nil, NULL, NULL, true, false));
validate(tp_type, pk_newtype("type", tp_object, NULL, NULL, false, true));
pk_object__register();
validate(tp_int, pk_newtype("int", tp_object, NULL, NULL, false, true));
validate(tp_float, pk_newtype("float", tp_object, NULL, NULL, false, true));
validate(tp_bool, pk_newtype("bool", tp_object, NULL, NULL, false, true));
pk_number__register();
validate(tp_str, pk_str__register());
validate(tp_str_iterator, pk_str_iterator__register());
validate(tp_list, pk_list__register());
validate(tp_tuple, pk_tuple__register());
validate(tp_list_iterator, pk_list_iterator__register());
validate(tp_tuple_iterator, pk_tuple_iterator__register());
validate(tp_slice, pk_slice__register());
validate(tp_range, pk_range__register());
validate(tp_range_iterator, pk_range_iterator__register());
validate(tp_module, pk_module__register());
validate(tp_function, pk_function__register());
validate(tp_nativefunc, pk_nativefunc__register());
validate(tp_boundmethod, pk_boundmethod__register());
validate(tp_super, pk_super__register());
validate(tp_BaseException, pk_BaseException__register());
validate(tp_Exception, pk_Exception__register());
validate(tp_bytes, pk_bytes__register());
validate(tp_namedict, pk_namedict__register());
validate(tp_locals, pk_newtype("locals", tp_object, NULL, NULL, false, true));
validate(tp_code, pk_code__register());
validate(tp_dict, pk_dict__register());
validate(tp_dict_iterator, pk_dict_items__register());
validate(tp_property, pk_property__register());
validate(tp_star_wrapper, pk_newtype("star_wrapper", tp_object, NULL, NULL, false, true));
validate(tp_staticmethod, pk_staticmethod__register());
validate(tp_classmethod, pk_classmethod__register());
validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true));
validate(tp_NotImplementedType,
pk_newtype("NotImplementedType", tp_object, NULL, NULL, false, true));
validate(tp_ellipsis, pk_newtype("ellipsis", tp_object, NULL, NULL, false, true));
validate(tp_generator, pk_generator__register());
self->builtins = pk_builtins__register();
// inject some builtin exceptions
#define INJECT_BUILTIN_EXC(name, TBase) \
do { \
py_Type type = pk_newtype(#name, TBase, self->builtins, NULL, false, true); \
py_setdict(self->builtins, py_name(#name), py_tpobject(type)); \
validate(tp_##name, type); \
} while(0)
INJECT_BUILTIN_EXC(SystemExit, tp_BaseException);
INJECT_BUILTIN_EXC(KeyboardInterrupt, tp_BaseException);
validate(tp_StopIteration, pk_StopIteration__register());
py_setdict(self->builtins, py_name("StopIteration"), py_tpobject(tp_StopIteration));
INJECT_BUILTIN_EXC(SyntaxError, tp_Exception);
INJECT_BUILTIN_EXC(RecursionError, tp_Exception);
INJECT_BUILTIN_EXC(OSError, tp_Exception);
INJECT_BUILTIN_EXC(NotImplementedError, tp_Exception);
INJECT_BUILTIN_EXC(TypeError, tp_Exception);
INJECT_BUILTIN_EXC(IndexError, tp_Exception);
INJECT_BUILTIN_EXC(ValueError, tp_Exception);
INJECT_BUILTIN_EXC(RuntimeError, tp_Exception);
INJECT_BUILTIN_EXC(TimeoutError, tp_Exception);
INJECT_BUILTIN_EXC(ZeroDivisionError, tp_Exception);
INJECT_BUILTIN_EXC(NameError, tp_Exception);
INJECT_BUILTIN_EXC(UnboundLocalError, tp_Exception);
INJECT_BUILTIN_EXC(AttributeError, tp_Exception);
INJECT_BUILTIN_EXC(ImportError, tp_Exception);
INJECT_BUILTIN_EXC(AssertionError, tp_Exception);
INJECT_BUILTIN_EXC(KeyError, tp_Exception);
#undef INJECT_BUILTIN_EXC
#undef validate
/* Setup Public Builtin Types */
py_Type public_types[] = {
tp_object,
tp_type,
tp_int,
tp_float,
tp_bool,
tp_str,
tp_list,
tp_tuple,
tp_slice,
tp_range,
tp_bytes,
tp_dict,
tp_property,
tp_staticmethod,
tp_classmethod,
tp_super,
tp_BaseException,
tp_Exception,
};
for(int i = 0; i < c11__count_array(public_types); i++) {
py_TypeInfo* ti = pk_typeinfo(public_types[i]);
py_setdict(self->builtins, ti->name, &ti->self);
}
py_newnotimplemented(py_emplacedict(self->builtins, py_name("NotImplemented")));
pk__add_module_stdc();
pk__add_module_vmath();
pk__add_module_array2d();
// pk__add_module_colorcvt();
// add modules
pk__add_module_os();
pk__add_module_sys();
pk__add_module_io();
pk__add_module_math();
pk__add_module_dis();
pk__add_module_random();
pk__add_module_json();
pk__add_module_gc();
pk__add_module_time();
pk__add_module_easing();
pk__add_module_traceback();
pk__add_module_enum();
pk__add_module_inspect();
pk__add_module_pickle();
pk__add_module_base64();
pk__add_module_importlib();
pk__add_module_unicodedata();
pk__add_module_conio();
pk__add_module_lz4(); // optional
pk__add_module_cute_png(); // optional
pk__add_module_msgpack(); // optional
py__add_module_periphery(); // optional
pk__add_module_pkpy();
pk__add_module_picoterm();
// add python builtins
do {
bool ok;
ok = py_exec(kPythonLibs_builtins, "<builtins>", EXEC_MODE, self->builtins);
if(!ok) goto __ABORT;
break;
__ABORT:
py_printexc();
c11__abort("failed to load python builtins!");
} while(0);
self->main = py_newmodule("__main__");
if(py_appcallbacks()->on_vm_ctor) {
int index = VM__index(self);
py_appcallbacks()->on_vm_ctor(index);
}
}
void VM__dtor(VM* self) {
if(py_appcallbacks()->on_vm_dtor) {
int index = VM__index(self);
py_appcallbacks()->on_vm_dtor(index);
}
// reset traceinfo
py_sys_settrace(NULL, true);
LineProfiler__dtor(&self->line_profiler);
// destroy all objects
ManagedHeap__dtor(&self->heap);
// clear frames
while(self->top_frame) {
VM__pop_frame(self);
}
BinTree__dtor(&self->modules);
FixedMemoryPool__dtor(&self->pool_frame);
CachedNames__dtor(&self->cached_names);
c11_vector__dtor(&self->types);
}
void VM__push_frame(VM* self, py_Frame* frame) {
frame->f_back = self->top_frame;
self->top_frame = frame;
self->recursion_depth++;
if(self->trace_info.func) self->trace_info.func(frame, TRACE_EVENT_PUSH);
}
void VM__pop_frame(VM* self) {
assert(self->top_frame);
py_Frame* frame = self->top_frame;
if(self->trace_info.func) self->trace_info.func(frame, TRACE_EVENT_POP);
// reset stack pointer
self->stack.sp = frame->p0;
// pop frame and delete
self->top_frame = frame->f_back;
Frame__delete(frame);
self->recursion_depth--;
}
static void _clip_int(int* value, int min, int max) {
if(*value < min) *value = min;
if(*value > max) *value = max;
}
bool pk__parse_int_slice(py_Ref slice,
int length,
int* restrict start,
int* restrict stop,
int* restrict step) {
if(py_isint(slice)) {
int index = py_toint(slice);
bool ok = pk__normalize_index(&index, length);
if(!ok) return false;
*start = index;
*stop = index + 1;
*step = 1;
return true;
}
if(!py_istype(slice, tp_slice)) c11__abort("pk__parse_int_slice(): not a slice object");
py_Ref s_start = py_getslot(slice, 0);
py_Ref s_stop = py_getslot(slice, 1);
py_Ref s_step = py_getslot(slice, 2);
if(py_isnone(s_step))
*step = 1;
else {
if(!py_checkint(s_step)) return false;
*step = py_toint(s_step);
}
if(*step == 0) return ValueError("slice step cannot be zero");
if(*step > 0) {
if(py_isnone(s_start))
*start = 0;
else {
if(!py_checkint(s_start)) return false;
*start = py_toint(s_start);
if(*start < 0) *start += length;
_clip_int(start, 0, length);
}
if(py_isnone(s_stop))
*stop = length;
else {
if(!py_checkint(s_stop)) return false;
*stop = py_toint(s_stop);
if(*stop < 0) *stop += length;
_clip_int(stop, 0, length);
}
} else {
if(py_isnone(s_start))
*start = length - 1;
else {
if(!py_checkint(s_start)) return false;
*start = py_toint(s_start);
if(*start < 0) *start += length;
_clip_int(start, -1, length - 1);
}
if(py_isnone(s_stop))
*stop = -1;
else {
if(!py_checkint(s_stop)) return false;
*stop = py_toint(s_stop);
if(*stop < 0) *stop += length;
_clip_int(stop, -1, length - 1);
}
}
return true;
}
bool pk__normalize_index(int* index, int length) {
if(*index < 0) *index += length;
if(*index < 0 || *index >= length) return IndexError("%d not in [0, %d)", *index, length);
return true;
}
static bool
prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) {
const CodeObject* co = &decl->code;
int decl_argc = decl->args.length;
if(p1 - argv < decl_argc) {
return TypeError("%s() takes %d positional arguments but %d were given",
co->name->data,
decl_argc,
(int)(p1 - argv));
}
py_TValue* t = argv;
// prepare args
memset(buffer, 0, co->nlocals * sizeof(py_TValue));
c11__foreach(int, &decl->args, index) buffer[*index] = *t++;
// prepare kwdefaults
c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) buffer[kv->index] = kv->value;
// handle *args
if(decl->starred_arg != -1) {
int exceed_argc = p1 - t;
py_Ref vargs = &buffer[decl->starred_arg];
py_Ref data = py_newtuple(vargs, exceed_argc);
for(int j = 0; j < exceed_argc; j++) {
data[j] = *t++;
}
} else {
// kwdefaults override
// def f(a, b, c=None)
// f(1, 2, 3) -> c=3
c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
if(t >= p1) break;
buffer[kv->index] = *t++;
}
// not able to consume all args
if(t < p1) return TypeError("too many arguments (%s)", co->name->data);
}
if(decl->starred_kwarg != -1) py_newdict(&buffer[decl->starred_kwarg]);
for(int j = 0; j < kwargc; j++) {
py_Name key = (py_Name)py_toint(&p1[2 * j]);
int index = c11_smallmap_n2d__get(&decl->kw_to_index, key, -1);
// if key is an explicit key, set as local variable
if(index >= 0) {
buffer[index] = p1[2 * j + 1];
} else {
// otherwise, set as **kwargs if possible
if(decl->starred_kwarg == -1) {
return TypeError("'%n' is an invalid keyword argument for %s()",
key,
co->name->data);
} else {
// add to **kwargs
bool ok =
py_dict_setitem(&buffer[decl->starred_kwarg], py_name2ref(key), &p1[2 * j + 1]);
if(!ok) return false;
}
}
}
return true;
}
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
#ifndef NDEBUG
pk_print_stack(self, self->top_frame, (Bytecode){0});
if(py_checkexc()) {
const char* name = py_tpname(self->unhandled_exc.type);
c11__abort("unhandled exception `%s` was set!", name);
}
#endif
py_StackRef p1 = self->stack.sp - kwargc * 2;
py_StackRef p0 = p1 - argc - 2;
// [callable, <self>, args..., kwargs...]
// ^p0 ^p1 ^_sp
// handle boundmethod, do a patch
if(p0->type == tp_boundmethod) {
assert(py_isnil(p0 + 1)); // self must be NULL
py_TValue* slots = PyObject__slots(p0->_obj);
p0[0] = slots[1]; // callable
p0[1] = slots[0]; // self
// [unbound, self, args..., kwargs...]
}
py_StackRef argv = p0 + 1 + (int)py_isnil(p0 + 1);
self->curr_function = p0; // set current function for inspection
if(p0->type == tp_function) {
Function* fn = py_touserdata(p0);
const CodeObject* co = &fn->decl->code;
switch(fn->decl->type) {
case FuncType_NORMAL: {
bool ok = prepare_py_call(self->vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR;
// copy buffer back to stack
self->stack.sp = argv + co->nlocals;
memcpy(argv, self->vectorcall_buffer, co->nlocals * sizeof(py_TValue));
// submit the call
if(!fn->cfunc) {
// python function
VM__push_frame(self, Frame__new(co, p0, fn->module, &fn->globals, argv, false));
return opcall ? RES_CALL : VM__run_top_frame(self);
} else {
// decl-based binding
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
self->stack.sp = p0;
return ok ? RES_RETURN : RES_ERROR;
}
}
case FuncType_SIMPLE:
if(p1 - argv != fn->decl->args.length) {
const char* fmt = "%s() takes %d positional arguments but %d were given";
TypeError(fmt, co->name->data, fn->decl->args.length, (int)(p1 - argv));
return RES_ERROR;
}
if(kwargc) {
TypeError("%s() takes no keyword arguments", co->name->data);
return RES_ERROR;
}
// [callable, <self>, args..., local_vars...]
// ^p0 ^p1 ^_sp
self->stack.sp = argv + co->nlocals;
// initialize local variables to py_NIL
memset(p1, 0, (char*)self->stack.sp - (char*)p1);
// submit the call
if(!fn->cfunc) {
// python function
VM__push_frame(self, Frame__new(co, p0, fn->module, &fn->globals, argv, false));
return opcall ? RES_CALL : VM__run_top_frame(self);
} else {
// decl-based binding
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
self->stack.sp = p0;
return ok ? RES_RETURN : RES_ERROR;
}
case FuncType_GENERATOR: {
bool ok = prepare_py_call(self->vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR;
// copy buffer back to stack
self->stack.sp = argv + co->nlocals;
memcpy(argv, self->vectorcall_buffer, co->nlocals * sizeof(py_TValue));
py_Frame* frame = Frame__new(co, p0, fn->module, &fn->globals, argv, false);
pk_newgenerator(py_retval(), frame, p0, self->stack.sp);
self->stack.sp = p0; // reset the stack
return RES_RETURN;
}
default: c11__unreachable();
};
c11__unreachable();
/*****************_py_call*****************/
}
if(p0->type == tp_nativefunc) {
if(kwargc && p0->_cfunc != pk__object_new) {
TypeError("nativefunc does not accept keyword arguments");
return RES_ERROR;
}
bool ok = py_callcfunc(p0->_cfunc, p1 - argv, argv);
self->stack.sp = p0;
return ok ? RES_RETURN : RES_ERROR;
}
if(p0->type == tp_type) {
// [cls, NULL, args..., kwargs...]
py_Ref new_f = py_tpfindmagic(py_totype(p0), __new__);
assert(new_f && py_isnil(p0 + 1));
bool is_default_new = new_f->type == tp_nativefunc && new_f->_cfunc == pk__object_new;
// prepare a copy of args and kwargs
int span = self->stack.sp - argv;
*self->stack.sp++ = *new_f; // push __new__
*self->stack.sp++ = *p0; // push cls
memcpy(self->stack.sp, argv, span * sizeof(py_TValue));
self->stack.sp += span;
// [new_f, cls, args..., kwargs...]
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
// by recursively using vectorcall, args and kwargs are consumed
// try __init__
// NOTE: previously we use `get_unbound_method` but here we just use `tpfindmagic`
// >> [cls, NULL, args..., kwargs...]
// >> py_retval() is the new instance
py_Ref init_f = py_tpfindmagic(py_totype(p0), __init__);
if(init_f) {
// do an inplace patch
*p0 = *init_f; // __init__
p0[1] = self->last_retval; // self
// [__init__, self, args..., kwargs...]
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
*py_retval() = p0[1]; // restore the new instance
} else {
if(is_default_new) {
if(argc != 0 || kwargc != 0) {
TypeError("%t() takes no arguments", py_totype(p0));
return RES_ERROR;
}
}
}
// reset the stack
self->stack.sp = p0;
return RES_RETURN;
}
// handle `__call__` overload
if(pk_loadmethod(p0, __call__)) {
// [__call__, self, args..., kwargs...]
return VM__vectorcall(self, argc, kwargc, opcall);
}
TypeError("'%t' object is not callable", p0->type);
return RES_ERROR;
}
/****************************************/
void FuncDecl__gc_mark(const FuncDecl* self, c11_vector* p_stack) {
CodeObject__gc_mark(&self->code, p_stack);
for(int j = 0; j < self->kwargs.length; j++) {
FuncDeclKwArg* kw = c11__at(FuncDeclKwArg, &self->kwargs, j);
pk__mark_value(&kw->value);
}
}
void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack) {
for(int i = 0; i < self->consts.length; i++) {
py_TValue* p = c11__at(py_TValue, &self->consts, i);
pk__mark_value(p);
}
for(int i = 0; i < self->func_decls.length; i++) {
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
FuncDecl__gc_mark(decl, p_stack);
}
}
static void pk__mark_value_func(py_Ref val, void* ctx) {
c11_vector* p_stack = ctx;
pk__mark_value(val);
}
void ManagedHeap__mark(ManagedHeap* self) {
VM* vm = pk_current_vm;
c11_vector* p_stack = &self->gc_roots;
assert(p_stack->length == 0);
// mark value stack
for(py_TValue* p = vm->stack.begin; p < vm->stack.sp; p++) {
// assert(p->type != tp_nil);
pk__mark_value(p);
}
// mark modules
BinTree__apply_mark(&vm->modules, p_stack);
// mark cached names
for(int i = 0; i < vm->cached_names.entries.length; i++) {
CachedNames_KV* kv = c11_chunkedvector__at(&vm->cached_names.entries, i);
pk__mark_value(&kv->val);
}
// mark types
int types_length = vm->types.length;
// 0-th type is placeholder
for(py_Type i = 1; i < types_length; i++) {
py_TypeInfo* ti = c11__getitem(TypePointer, &vm->types, i).ti;
pk__mark_value(&ti->self);
pk__mark_value(&ti->annotations);
}
// mark frame
for(py_Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
Frame__gc_mark(frame, p_stack);
}
// mark vm's registers
pk__mark_value(&vm->last_retval);
pk__mark_value(&vm->unhandled_exc);
for(int i = 0; i < c11__count_array(vm->reg); i++) {
pk__mark_value(&vm->reg[i]);
}
// mark gc debug callback
pk__mark_value(&vm->heap.debug_callback);
// mark user func
if(vm->callbacks.gc_mark) vm->callbacks.gc_mark(pk__mark_value_func, p_stack);
/*****************************/
while(p_stack->length > 0) {
PyObject* obj = c11_vector__back(PyObject*, p_stack);
c11_vector__pop(p_stack);
assert(obj->gc_marked);
if(obj->slots > 0) {
py_TValue* p = PyObject__slots(obj);
for(int i = 0; i < obj->slots; i++)
pk__mark_value(p + i);
} else if(obj->slots == -1) {
NameDict* dict = PyObject__dict(obj);
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
pk__mark_value(&kv->value);
}
}
void* ud = PyObject__userdata(obj);
switch(obj->type) {
case tp_list: {
List* self = ud;
for(int i = 0; i < self->length; i++) {
py_TValue* val = c11__at(py_TValue, self, i);
pk__mark_value(val);
}
break;
}
case tp_dict: {
Dict* self = ud;
for(int i = 0; i < self->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
pk__mark_value(&entry->key);
pk__mark_value(&entry->val);
}
break;
}
case tp_generator: {
Generator* self = ud;
if(self->frame) Frame__gc_mark(self->frame, p_stack);
break;
}
case tp_function: {
function__gc_mark(ud, p_stack);
break;
}
case tp_BaseException: {
BaseException* self = ud;
pk__mark_value(&self->args);
pk__mark_value(&self->inner_exc);
c11__foreach(BaseExceptionFrame, &self->stacktrace, frame) {
pk__mark_value(&frame->locals);
pk__mark_value(&frame->globals);
}
break;
}
case tp_code: {
CodeObject* self = ud;
CodeObject__gc_mark(self, p_stack);
break;
}
case tp_chunked_array2d: {
c11_chunked_array2d__mark(ud, p_stack);
break;
}
}
}
}
// src/interpreter\vmx.c
#include <assert.h>
void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte) {
return;
if(frame == NULL || !self->main || py_isnil(self->main)) return;
py_TValue* sp = self->stack.sp;
c11_sbuf buf;
c11_sbuf__ctor(&buf);
for(py_Ref p = self->stack.begin; p != sp; p++) {
switch(p->type) {
case tp_nil: c11_sbuf__write_cstr(&buf, "nil"); break;
case tp_int: c11_sbuf__write_i64(&buf, p->_i64); break;
case tp_float: c11_sbuf__write_f64(&buf, p->_f64, -1); break;
case tp_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break;
case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break;
case tp_list: {
pk_sprintf(&buf, "list(%d)", py_list_len(p));
break;
}
case tp_tuple: {
pk_sprintf(&buf, "tuple(%d)", py_tuple_len(p));
break;
}
case tp_function: {
Function* ud = py_touserdata(p);
c11_sbuf__write_cstr(&buf, ud->decl->code.name->data);
c11_sbuf__write_cstr(&buf, "()");
break;
}
case tp_type: {
pk_sprintf(&buf, "<class '%t'>", py_totype(p));
break;
}
case tp_str: {
pk_sprintf(&buf, "%q", py_tosv(p));
break;
}
case tp_module: {
py_ModuleInfo* mi = py_touserdata(p);
pk_sprintf(&buf, "<module '%v'>", c11_string__sv(mi->path));
break;
}
default: {
pk_sprintf(&buf, "(%t)", p->type);
break;
}
}
if(p != &sp[-1]) c11_sbuf__write_cstr(&buf, ", ");
}
c11_string* stack_str = c11_sbuf__submit(&buf);
printf("%s:%-3d: %-25s %-6d [%s]\n",
frame->co->src->filename->data,
Frame__lineno(frame),
pk_opname(byte.op),
byte.arg,
stack_str->data);
c11_string__delete(stack_str);
}
bool pk_wrapper__self(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), argv);
return true;
}
int py_replinput(char* buf, int max_size) {
buf[0] = '\0'; // reset first char because we check '@' at the beginning
int size = 0;
bool multiline = false;
printf(">>> ");
while(true) {
int c = pk_current_vm->callbacks.getchr();
if(c == EOF) return -1;
if(c == '\n') {
char last = '\0';
if(size > 0) last = buf[size - 1];
if(multiline) {
if(last == '\n') {
break; // 2 consecutive newlines to end multiline input
} else {
printf("... ");
}
} else {
if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
printf("... ");
multiline = true;
} else {
break;
}
}
}
if(size == max_size - 1) {
buf[size] = '\0';
return size;
}
buf[size++] = c;
}
buf[size] = '\0';
return size;
}
py_Ref py_name2ref(py_Name name) {
assert(name != NULL);
CachedNames* d = &pk_current_vm->cached_names;
py_Ref res = CachedNames__try_get(d, name);
if(res != NULL) return res;
// not found, create a new one
py_newstrv(py_tmpr0(), py_name2sv(name));
CachedNames__set(d, name, py_tmpr0());
return CachedNames__try_get(d, name);
}
void PyObject__dtor(PyObject* self) {
py_Dtor dtor = c11__getitem(TypePointer, &pk_current_vm->types, self->type).dtor;
if(dtor) dtor(PyObject__userdata(self));
if(self->slots == -1) {
NameDict* dict = PyObject__dict(self);
NameDict__dtor(dict);
}
}
ManagedHeapSwpetInfo* ManagedHeapSwpetInfo__new() {
ManagedHeapSwpetInfo* self = py_malloc(sizeof(ManagedHeapSwpetInfo));
memset(self, 0, sizeof(ManagedHeapSwpetInfo));
self->types_length = pk_current_vm->types.length;
self->small_types = py_malloc(sizeof(int) * self->types_length);
self->large_types = py_malloc(sizeof(int) * self->types_length);
for(int i = 0; i < self->types_length; i++) {
self->small_types[i] = 0;
self->large_types[i] = 0;
}
self->start_ns = time_ns();
return self;
}
void ManagedHeapSwpetInfo__delete(ManagedHeapSwpetInfo* self) {
py_free(self->small_types);
py_free(self->large_types);
memset(self, 0, sizeof(ManagedHeapSwpetInfo));
py_free(self);
}
// src/modules\array2d.c
#include <limits.h>
static bool c11_array2d_like_is_valid(c11_array2d_like* self, int col, int row) {
return col >= 0 && col < self->n_cols && row >= 0 && row < self->n_rows;
}
static py_Ref c11_array2d__get(c11_array2d* self, int col, int row) {
return self->data + row * self->header.n_cols + col;
}
static bool c11_array2d__set(c11_array2d* self, int col, int row, py_Ref value) {
self->data[row * self->header.n_cols + col] = *value;
return true;
}
c11_array2d* c11_newarray2d(py_OutRef out, int n_cols, int n_rows) {
int numel = n_cols * n_rows;
c11_array2d* ud = py_newobject(out, tp_array2d, numel, sizeof(c11_array2d));
ud->header.n_cols = n_cols;
ud->header.n_rows = n_rows;
ud->header.numel = numel;
ud->header.f_get = (py_Ref (*)(c11_array2d_like*, int, int))c11_array2d__get;
ud->header.f_set = (bool (*)(c11_array2d_like*, int, int, py_Ref))c11_array2d__set;
ud->data = py_getslot(out, 0);
return ud;
}
/* array2d_like bindings */
static bool array2d_like_n_cols(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
py_newint(py_retval(), self->n_cols);
return true;
}
static bool array2d_like_n_rows(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
py_newint(py_retval(), self->n_rows);
return true;
}
static bool array2d_like_shape(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
c11_vec2i shape;
shape.x = self->n_cols;
shape.y = self->n_rows;
py_newvec2i(py_retval(), shape);
return true;
}
static bool array2d_like_numel(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
py_newint(py_retval(), self->numel);
return true;
}
static bool array2d_like_is_valid(int argc, py_Ref argv) {
c11_array2d_like* self = py_touserdata(argv);
int col, row;
if(argc == 2) {
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_vec2i pos = py_tovec2i(py_arg(1));
col = pos.x;
row = pos.y;
} else if(argc == 3) {
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
col = py_toint(py_arg(1));
row = py_toint(py_arg(2));
} else {
return TypeError("is_valid() expected 2 or 3 arguments");
}
py_newbool(py_retval(), c11_array2d_like_is_valid(self, col, row));
return true;
}
static bool array2d_like_get(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
py_Ref default_;
c11_array2d_like* self = py_touserdata(argv);
if(argc == 3) {
default_ = py_None();
} else if(argc == 4) {
default_ = py_arg(3);
} else {
return TypeError("get() expected 2 or 3 arguments");
}
int col = py_toint(py_arg(1));
int row = py_toint(py_arg(2));
if(c11_array2d_like_is_valid(self, col, row)) {
py_assign(py_retval(), self->f_get(self, col, row));
} else {
py_assign(py_retval(), default_);
}
return true;
}
static bool array2d_like_index(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
py_Ref value = py_arg(1);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
int code = py_equal(item, value);
if(code == -1) return false;
if(code == 1) {
py_newvec2i(py_retval(),
(c11_vec2i){
{i, j}
});
return true;
}
}
}
return ValueError("value not found");
}
static bool array2d_like_render(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_array2d_like* self = py_touserdata(argv);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_str(item)) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
}
if(j < self->n_rows - 1) c11_sbuf__write_char(&buf, '\n');
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
void c11_color32_premult(c11_color32* color);
static bool array2d_like_render_with_color(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_array2d_like* self = py_touserdata(argv);
if(!py_checkinstance(py_arg(1), tp_array2d_like)) return false;
if(!py_checkinstance(py_arg(2), tp_array2d_like)) return false;
c11_array2d_like* fg_colors = py_touserdata(py_arg(1));
c11_array2d_like* bg_colors = py_touserdata(py_arg(2));
c11_color32 curr_fg, curr_bg;
curr_fg.u32 = 0;
curr_bg.u32 = 0;
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_str(item)) {
c11_sbuf__dtor(&buf);
return false;
}
py_Ref fg_item = fg_colors->f_get(fg_colors, i, j);
py_Ref bg_item = bg_colors->f_get(bg_colors, i, j);
c11_color32 new_fg, new_bg;
if(py_isnone(fg_item)) {
new_fg.u32 = 0;
} else {
if(!py_checktype(fg_item, tp_color32)) {
c11_sbuf__dtor(&buf);
return false;
}
new_fg = py_tocolor32(fg_item);
}
if(py_isnone(bg_item)) {
new_bg.u32 = 0;
} else {
if(!py_checktype(bg_item, tp_color32)) {
c11_sbuf__dtor(&buf);
return false;
}
new_bg = py_tocolor32(bg_item);
}
if(curr_fg.u32 != new_fg.u32 || curr_bg.u32 != new_bg.u32) {
if(curr_fg.u32 != 0 || curr_bg.u32 != 0) c11_sbuf__write_cstr(&buf, "\x1b[0m");
curr_fg = new_fg;
curr_bg = new_bg;
if(curr_fg.u32 != 0) {
c11_color32_premult(&curr_fg);
pk_sprintf(&buf, "\x1b[38;2;%d;%d;%dm", curr_fg.r, curr_fg.g, curr_fg.b);
}
if(curr_bg.u32 != 0) {
c11_color32_premult(&curr_bg);
pk_sprintf(&buf, "\x1b[48;2;%d;%d;%dm", curr_bg.r, curr_bg.g, curr_bg.b);
}
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
}
// newline
if(j < self->n_rows - 1) {
curr_fg.u32 = 0;
curr_bg.u32 = 0;
c11_sbuf__write_cstr(&buf, "\x1b[0m\n");
} else {
c11_sbuf__write_cstr(&buf, "\x1b[0m");
}
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool array2d_like_all(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_checkbool(item)) return false;
if(!py_tobool(item)) {
py_newbool(py_retval(), false);
return true;
}
}
}
py_newbool(py_retval(), true);
return true;
}
static bool array2d_like_any(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_checkbool(item)) return false;
if(py_tobool(item)) {
py_newbool(py_retval(), true);
return true;
}
}
}
py_newbool(py_retval(), false);
return true;
}
static bool array2d_like_map(int argc, py_Ref argv) {
// def map(self, f: Callable[[T], Any]) -> 'array2d': ...
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
py_Ref f = py_arg(1);
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_call(f, 1, item)) return false;
res->data[j * self->n_cols + i] = *py_retval();
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
static bool array2d_like_apply(int argc, py_Ref argv) {
// def apply_(self, f: Callable[[T], T]) -> None: ...
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
py_Ref f = py_arg(1);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!py_call(f, 1, item)) return false;
bool ok = self->f_set(self, i, j, py_retval());
if(!ok) return false;
}
}
py_newnone(py_retval());
return true;
}
static bool _check_same_shape(int colA, int rowA, int colB, int rowB) {
if(colA != colB || rowA != rowB) {
const char* fmt = "expected the same shape: (%d, %d) != (%d, %d)";
return ValueError(fmt, colA, rowA, colB, rowB);
}
return true;
}
static bool _array2d_like_check_same_shape(c11_array2d_like* self, c11_array2d_like* other) {
return _check_same_shape(self->n_cols, self->n_rows, other->n_cols, other->n_rows);
}
static bool _array2d_like_broadcasted_zip_with(int argc, py_Ref argv, py_Name op, py_Name rop) {
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
c11_array2d_like* other;
if(py_isinstance(py_arg(1), tp_array2d_like)) {
other = py_touserdata(py_arg(1));
if(!_array2d_like_check_same_shape(self, other)) return false;
} else {
other = NULL;
}
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref lhs = self->f_get(self, i, j);
py_Ref rhs;
if(other != NULL) {
rhs = other->f_get(other, i, j);
} else {
rhs = py_arg(1); // broadcast
}
if(!py_binaryop(lhs, rhs, op, rop)) return false;
c11_array2d__set(res, i, j, py_retval());
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
static bool array2d_like_zip_with(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
c11_array2d_like* self = py_touserdata(argv);
if(!py_checkinstance(py_arg(1), tp_array2d_like)) return false;
c11_array2d_like* other = py_touserdata(py_arg(1));
py_Ref f = py_arg(2);
if(!_array2d_like_check_same_shape(self, other)) return false;
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_push(f);
py_pushnil();
py_push(self->f_get(self, i, j));
py_push(other->f_get(other, i, j));
if(!py_vectorcall(2, 0)) return false;
c11_array2d__set(res, i, j, py_retval());
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
#define DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(name, op, rop) \
static bool array2d_like##name(int argc, py_Ref argv) { \
return _array2d_like_broadcasted_zip_with(argc, argv, op, rop); \
}
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__le__, __le__, __ge__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__lt__, __lt__, __gt__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__ge__, __ge__, __le__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__gt__, __gt__, __lt__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__eq__, __eq__, __eq__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__ne__, __ne__, __ne__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__add__, __add__, __radd__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__sub__, __sub__, __rsub__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__mul__, __mul__, __rmul__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__truediv__, __truediv__, __rtruediv__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__floordiv__, __floordiv__, __rfloordiv__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__mod__, __mod__, __rmod__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__pow__, __pow__, __rpow__)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__and__, __and__, 0)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__or__, __or__, 0)
DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH(__xor__, __xor__, 0)
#undef DEF_ARRAY2D_LIKE__MAGIC_ZIP_WITH
static bool array2d_like__invert__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
if(!pk_callmagic(__invert__, 1, item)) return false;
c11_array2d__set(res, i, j, py_retval());
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
static bool array2d_like_copy(int argc, py_Ref argv) {
// def copy(self) -> 'array2d': ...
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
c11_array2d* res = c11_newarray2d(py_retval(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
res->data[j * self->n_cols + i] = *item;
}
}
return true;
}
static bool array2d_like_tolist(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
py_newlistn(py_retval(), self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
py_Ref row_j = py_list_getitem(py_retval(), j);
py_newlistn(row_j, self->n_cols);
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
py_list_setitem(row_j, i, item);
}
}
return true;
}
static bool array2d_like__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
c11_array2d_like_iterator* ud =
py_newobject(py_retval(), tp_array2d_like_iterator, 1, sizeof(c11_array2d_like_iterator));
py_setslot(py_retval(), 0, argv); // keep the array alive
ud->array = self;
ud->j = 0;
ud->i = 0;
return true;
}
static bool array2d_like__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like* self = py_touserdata(argv);
char buf[256];
snprintf(buf,
sizeof(buf),
"%s(%d, %d)",
py_tpname(py_typeof(argv)),
self->n_cols,
self->n_rows);
py_newstr(py_retval(), buf);
return true;
}
#define HANDLE_SLICE() \
int start_col, stop_col, step_col; \
int start_row, stop_row, step_row; \
if(!pk__parse_int_slice(x, self->n_cols, &start_col, &stop_col, &step_col)) return false; \
if(!pk__parse_int_slice(y, self->n_rows, &start_row, &stop_row, &step_row)) return false; \
if(step_col != 1 || step_row != 1) return ValueError("slice step must be 1"); \
int slice_width = stop_col - start_col; \
int slice_height = stop_row - start_row;
static bool _array2d_like_IndexError(c11_array2d_like* self, int col, int row) {
return IndexError("(%d, %d) is not a valid index of array2d_like(%d, %d)",
col,
row,
self->n_cols,
self->n_rows);
}
static py_Ref c11_array2d_view__get(c11_array2d_view* self, int col, int row) {
return self->f_get(self->ctx, col + self->origin.x, row + self->origin.y);
}
static bool c11_array2d_view__set(c11_array2d_view* self, int col, int row, py_Ref value) {
return self->f_set(self->ctx, col + self->origin.x, row + self->origin.y, value);
}
static c11_array2d_view* _array2d_view__new(py_OutRef out,
py_Ref keepalive,
int start_col,
int start_row,
int width,
int height) {
c11_array2d_view* res = py_newobject(out, tp_array2d_view, 1, sizeof(c11_array2d_view));
if(width <= 0 || height <= 0) {
ValueError("width and height must be positive");
return NULL;
}
res->header.n_cols = width;
res->header.n_rows = height;
res->header.numel = width * height;
res->header.f_get = (py_Ref (*)(c11_array2d_like*, int, int))c11_array2d_view__get;
res->header.f_set = (bool (*)(c11_array2d_like*, int, int, py_Ref))c11_array2d_view__set;
res->origin.x = start_col;
res->origin.y = start_row;
py_setslot(out, 0, keepalive);
return res;
}
static bool _array2d_view(py_OutRef out,
py_Ref keepalive,
c11_array2d_like* array,
int start_col,
int start_row,
int width,
int height) {
c11_array2d_view* res = _array2d_view__new(out, keepalive, start_col, start_row, width, height);
if(res == NULL) return false;
res->ctx = array;
res->f_get = (py_Ref (*)(void*, int, int))array->f_get;
res->f_set = (bool (*)(void*, int, int, py_Ref))array->f_set;
return true;
}
static bool _chunked_array2d_view(py_OutRef out,
py_Ref keepalive,
c11_chunked_array2d* array,
int start_col,
int start_row,
int width,
int height) {
c11_array2d_view* res = _array2d_view__new(out, keepalive, start_col, start_row, width, height);
if(res == NULL) return false;
res->ctx = array;
res->f_get = (py_Ref (*)(void*, int, int))c11_chunked_array2d__get;
res->f_set = (bool (*)(void*, int, int, py_Ref))c11_chunked_array2d__set;
return true;
}
static bool array2d_like__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
if(argv[1].type == tp_vec2i) {
c11_vec2i pos = py_tovec2i(&argv[1]);
if(c11_array2d_like_is_valid(self, pos.x, pos.y)) {
py_assign(py_retval(), self->f_get(self, pos.x, pos.y));
return true;
}
return _array2d_like_IndexError(self, pos.x, pos.y);
}
if(py_isinstance(&argv[1], tp_array2d_like)) {
c11_array2d_like* mask = py_touserdata(&argv[1]);
if(!_array2d_like_check_same_shape(self, mask)) return false;
py_newlist(py_retval());
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
py_Ref cond = mask->f_get(mask, i, j);
if(!py_checkbool(cond)) return false;
if(py_tobool(cond)) py_list_append(py_retval(), item);
}
}
return true;
}
PY_CHECK_ARG_TYPE(1, tp_tuple);
if(py_tuple_len(&argv[1]) != 2) return TypeError("expected a tuple of 2 elements");
py_Ref x = py_tuple_getitem(&argv[1], 0);
py_Ref y = py_tuple_getitem(&argv[1], 1);
if(py_isint(x) && py_isint(y)) {
int col = py_toint(x);
int row = py_toint(y);
if(c11_array2d_like_is_valid(self, col, row)) {
py_assign(py_retval(), self->f_get(self, col, row));
return true;
}
return _array2d_like_IndexError(self, col, row);
}
bool _1 = py_istype(x, tp_slice) && py_istype(y, tp_slice);
bool _2 = py_istype(x, tp_int) && py_istype(y, tp_slice);
bool _3 = py_istype(x, tp_slice) && py_istype(y, tp_int);
if(_1 || _2 || _3) {
HANDLE_SLICE();
return _array2d_view(py_retval(),
argv,
self,
start_col,
start_row,
slice_width,
slice_height);
}
return TypeError("expected tuple[int, int] or tuple[slice, slice]");
}
static bool array2d_like__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
c11_array2d_like* self = py_touserdata(argv);
py_Ref value = &argv[2];
if(argv[1].type == tp_vec2i) {
c11_vec2i pos = py_tovec2i(&argv[1]);
if(c11_array2d_like_is_valid(self, pos.x, pos.y)) {
bool ok = self->f_set(self, pos.x, pos.y, value);
if(!ok) return false;
py_newnone(py_retval());
return true;
}
return _array2d_like_IndexError(self, pos.x, pos.y);
}
if(py_isinstance(&argv[1], tp_array2d_like)) {
c11_array2d_like* mask = py_touserdata(&argv[1]);
if(!_array2d_like_check_same_shape(self, mask)) return false;
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref cond = mask->f_get(mask, i, j);
if(!py_checkbool(cond)) return false;
if(py_tobool(cond)) {
bool ok = self->f_set(self, i, j, value);
if(!ok) return false;
}
}
}
py_newnone(py_retval());
return true;
}
PY_CHECK_ARG_TYPE(1, tp_tuple);
if(py_tuple_len(py_arg(1)) != 2) return TypeError("expected a tuple of 2 elements");
py_Ref x = py_tuple_getitem(py_arg(1), 0);
py_Ref y = py_tuple_getitem(py_arg(1), 1);
if(py_isint(x) && py_isint(y)) {
int col = py_toint(x);
int row = py_toint(y);
if(c11_array2d_like_is_valid(self, col, row)) {
bool ok = self->f_set(self, col, row, value);
if(!ok) return false;
py_newnone(py_retval());
return true;
}
return _array2d_like_IndexError(self, col, row);
}
bool _1 = py_istype(x, tp_slice) && py_istype(y, tp_slice);
bool _2 = py_istype(x, tp_int) && py_istype(y, tp_slice);
bool _3 = py_istype(x, tp_slice) && py_istype(y, tp_int);
if(_1 || _2 || _3) {
HANDLE_SLICE();
if(py_isinstance(value, tp_array2d_like)) {
c11_array2d_like* values = py_touserdata(value);
if(!_check_same_shape(slice_width, slice_height, values->n_cols, values->n_rows))
return false;
for(int j = 0; j < slice_height; j++) {
for(int i = 0; i < slice_width; i++) {
py_Ref item = values->f_get(values, i, j);
bool ok = self->f_set(self, start_col + i, start_row + j, item);
if(!ok) return false;
}
}
} else {
for(int j = 0; j < slice_height; j++) {
for(int i = 0; i < slice_width; i++) {
bool ok = self->f_set(self, start_col + i, start_row + j, value);
if(!ok) return false;
}
}
}
py_newnone(py_retval());
return true;
}
return TypeError("expected tuple[int, int] or tuple[slice, slice]");
}
// count(self, value: T) -> int
static bool array2d_like_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
int count = 0;
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
int code = py_equal(self->f_get(self, i, j), py_arg(1));
if(code == -1) return false;
count += code;
}
}
py_newint(py_retval(), count);
return true;
}
// get_bounding_rect(self, value: T) -> tuple[int, int, int, int]
static bool array2d_like_get_bounding_rect(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_array2d_like* self = py_touserdata(argv);
py_Ref value = py_arg(1);
int left = self->n_cols;
int top = self->n_rows;
int right = 0;
int bottom = 0;
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_Ref item = self->f_get(self, i, j);
int res = py_equal(item, value);
if(res == -1) return false;
if(res == 1) {
left = c11__min(left, i);
top = c11__min(top, j);
right = c11__max(right, i);
bottom = c11__max(bottom, j);
}
}
}
int width = right - left + 1;
int height = bottom - top + 1;
if(width <= 0 || height <= 0) {
return ValueError("value not found");
} else {
py_TValue* data = py_newtuple(py_retval(), 4);
py_newint(&data[0], left);
py_newint(&data[1], top);
py_newint(&data[2], width);
py_newint(&data[3], height);
}
return true;
}
// count_neighbors(self, value: T, neighborhood: Neighborhood) -> array2d[int]
static bool array2d_like_count_neighbors(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
c11_array2d_like* self = py_touserdata(argv);
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
py_Ref value = py_arg(1);
const char* neighborhood = py_tostr(py_arg(2));
const static c11_vec2i Moore[] = {
{{-1, -1}},
{{0, -1}},
{{1, -1}},
{{-1, 0}},
{{1, 0}},
{{-1, 1}},
{{0, 1}},
{{1, 1}},
};
const static c11_vec2i von_Neumann[] = {
{{0, -1}},
{{-1, 0}},
{{1, 0}},
{{0, 1}},
};
const c11_vec2i* offsets;
int n_offsets;
if(strcmp(neighborhood, "Moore") == 0) {
offsets = Moore;
n_offsets = c11__count_array(Moore);
} else if(strcmp(neighborhood, "von Neumann") == 0) {
offsets = von_Neumann;
n_offsets = c11__count_array(von_Neumann);
} else {
return ValueError("neighborhood must be 'Moore' or 'von Neumann'");
}
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_i64 count = 0;
for(int k = 0; k < n_offsets; k++) {
int x = i + offsets[k].x;
int y = j + offsets[k].y;
if(x >= 0 && x < self->n_cols && y >= 0 && y < self->n_rows) {
py_Ref item = self->f_get(self, x, y);
int code = py_equal(item, value);
if(code == -1) return false;
count += code;
}
}
py_newint(c11_array2d__get(res, i, j), count);
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
// convolve(self: array2d_like[int], kernel: array2d_like[int], padding: int) -> array2d[int]
static bool array2d_like_convolve(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
if(!py_checkinstance(&argv[1], tp_array2d_like)) return false;
PY_CHECK_ARG_TYPE(2, tp_int);
c11_array2d_like* self = py_touserdata(&argv[0]);
c11_array2d_like* kernel = py_touserdata(&argv[1]);
int padding = py_toint(py_arg(2));
if(kernel->n_cols != kernel->n_rows) return ValueError("kernel must be square");
int ksize = kernel->n_cols;
if(ksize % 2 == 0) return ValueError("kernel size must be odd");
int ksize_half = ksize / 2;
c11_array2d* res = c11_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
for(int j = 0; j < self->n_rows; j++) {
for(int i = 0; i < self->n_cols; i++) {
py_i64 sum = 0;
for(int jj = 0; jj < ksize; jj++) {
for(int ii = 0; ii < ksize; ii++) {
int x = i + ii - ksize_half;
int y = j + jj - ksize_half;
py_i64 _0, _1;
if(x < 0 || x >= self->n_cols || y < 0 || y >= self->n_rows) {
_0 = padding;
} else {
py_Ref item = self->f_get(self, x, y);
if(!py_checkint(item)) return false;
_0 = py_toint(item);
}
py_Ref kitem = kernel->f_get(kernel, ii, jj);
if(!py_checkint(kitem)) return false;
_1 = py_toint(kitem);
sum += _0 * _1;
}
}
py_newint(c11_array2d__get(res, i, j), sum);
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
#undef HANDLE_SLICE
static void register_array2d_like(py_Ref mod) {
py_Type type = py_newtype("array2d_like", tp_object, mod, NULL);
assert(type == tp_array2d_like);
py_bindproperty(type, "n_cols", array2d_like_n_cols, NULL);
py_bindproperty(type, "n_rows", array2d_like_n_rows, NULL);
py_bindproperty(type, "width", array2d_like_n_cols, NULL);
py_bindproperty(type, "height", array2d_like_n_rows, NULL);
py_bindproperty(type, "shape", array2d_like_shape, NULL);
py_bindproperty(type, "numel", array2d_like_numel, NULL);
py_bindmethod(type, "is_valid", array2d_like_is_valid);
py_bindmethod(type, "get", array2d_like_get);
py_bindmethod(type, "index", array2d_like_index);
py_bindmethod(type, "render", array2d_like_render);
py_bindmethod(type, "render_with_color", array2d_like_render_with_color);
py_bindmethod(type, "all", array2d_like_all);
py_bindmethod(type, "any", array2d_like_any);
py_bindmethod(type, "map", array2d_like_map);
py_bindmethod(type, "apply", array2d_like_apply);
py_bindmethod(type, "zip_with", array2d_like_zip_with);
py_bindmethod(type, "copy", array2d_like_copy);
py_bindmethod(type, "tolist", array2d_like_tolist);
py_bindmagic(type, __le__, array2d_like__le__);
py_bindmagic(type, __lt__, array2d_like__lt__);
py_bindmagic(type, __ge__, array2d_like__ge__);
py_bindmagic(type, __gt__, array2d_like__gt__);
py_bindmagic(type, __eq__, array2d_like__eq__);
py_bindmagic(type, __ne__, array2d_like__ne__);
py_bindmagic(type, __add__, array2d_like__add__);
py_bindmagic(type, __sub__, array2d_like__sub__);
py_bindmagic(type, __mul__, array2d_like__mul__);
py_bindmagic(type, __truediv__, array2d_like__truediv__);
py_bindmagic(type, __floordiv__, array2d_like__floordiv__);
py_bindmagic(type, __mod__, array2d_like__mod__);
py_bindmagic(type, __pow__, array2d_like__pow__);
py_bindmagic(type, __and__, array2d_like__and__);
py_bindmagic(type, __or__, array2d_like__or__);
py_bindmagic(type, __xor__, array2d_like__xor__);
py_bindmagic(type, __invert__, array2d_like__invert__);
py_bindmagic(type, __iter__, array2d_like__iter__);
py_bindmagic(type, __repr__, array2d_like__repr__);
py_bindmagic(type, __getitem__, array2d_like__getitem__);
py_bindmagic(type, __setitem__, array2d_like__setitem__);
py_bindmethod(type, "count", array2d_like_count);
py_bindmethod(type, "get_bounding_rect", array2d_like_get_bounding_rect);
py_bindmethod(type, "count_neighbors", array2d_like_count_neighbors);
py_bindmethod(type, "convolve", array2d_like_convolve);
const char* scc =
"\ndef get_connected_components(self, value: T, neighborhood: Neighborhood) -> tuple[array2d[int], int]:\n from collections import deque\n from vmath import vec2i\n\n DIRS = [vec2i.LEFT, vec2i.RIGHT, vec2i.UP, vec2i.DOWN]\n assert neighborhood in ['Moore', 'von Neumann']\n\n if neighborhood == 'Moore':\n DIRS.extend([\n vec2i.LEFT+vec2i.UP,\n vec2i.RIGHT+vec2i.UP,\n vec2i.LEFT+vec2i.DOWN,\n vec2i.RIGHT+vec2i.DOWN\n ])\n\n visited = array2d[int](self.width, self.height, default=0)\n queue = deque()\n count = 0\n for y in range(self.height):\n for x in range(self.width):\n if visited[x, y] or self[x, y] != value:\n continue\n count += 1\n queue.append((x, y))\n visited[x, y] = count\n while queue:\n cx, cy = queue.popleft()\n for dx, dy in DIRS:\n nx, ny = cx+dx, cy+dy\n if self.is_valid(nx, ny) and not visited[nx, ny] and self[nx, ny] == value:\n queue.append((nx, ny))\n visited[nx, ny] = count\n return visited, count\n\narray2d_like.get_connected_components = get_connected_components\ndel get_connected_components\n";
if(!py_exec(scc, "array2d.py", EXEC_MODE, mod)) {
py_printexc();
c11__abort("failed to execute array2d.py");
}
}
bool array2d_like_iterator__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_like_iterator* self = py_touserdata(argv);
if(self->j >= self->array->n_rows) return StopIteration();
py_TValue* data = py_newtuple(py_retval(), 2);
py_newvec2i(&data[0],
(c11_vec2i){
{self->i, self->j}
});
py_assign(&data[1], self->array->f_get(self->array, self->i, self->j));
self->i++;
if(self->i >= self->array->n_cols) {
self->i = 0;
self->j++;
}
return true;
}
static void register_array2d_like_iterator(py_Ref mod) {
py_Type type = py_newtype("array2d_like_iterator", tp_object, mod, NULL);
assert(type == tp_array2d_like_iterator);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, array2d_like_iterator__next__);
}
static bool array2d__new__(int argc, py_Ref argv) {
// __new__(cls, n_cols: int, n_rows: int, default: Callable[[vec2i], T] = None)
py_Ref default_ = py_arg(3);
PY_CHECK_ARG_TYPE(0, tp_type);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
int n_cols = argv[1]._i64;
int n_rows = argv[2]._i64;
if(n_cols <= 0 || n_rows <= 0) return ValueError("array2d() expected positive dimensions");
c11_array2d* ud = c11_newarray2d(py_pushtmp(), n_cols, n_rows);
// setup initial values
if(py_callable(default_)) {
for(int j = 0; j < n_rows; j++) {
for(int i = 0; i < n_cols; i++) {
py_TValue tmp;
py_newvec2i(&tmp,
(c11_vec2i){
{i, j}
});
if(!py_call(default_, 1, &tmp)) return false;
ud->data[j * n_cols + i] = *py_retval();
}
}
} else {
for(int i = 0; i < ud->header.numel; i++) {
ud->data[i] = *default_;
}
}
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
// fromlist(data: list[list[T]]) -> array2d[T]
static bool array2d_fromlist_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(!py_checktype(argv, tp_list)) return false;
int n_rows = py_list_len(argv);
if(n_rows == 0) return ValueError("fromlist() expected a non-empty list");
int n_cols = -1;
for(int j = 0; j < n_rows; j++) {
py_Ref row_j = py_list_getitem(argv, j);
if(!py_checktype(row_j, tp_list)) return false;
int n_cols_j = py_list_len(row_j);
if(n_cols == -1) {
if(n_cols_j == 0) return ValueError("fromlist() expected a non-empty list");
n_cols = n_cols_j;
} else if(n_cols != n_cols_j) {
return ValueError("fromlist() expected a list of lists with the same length");
}
}
c11_array2d* res = c11_newarray2d(py_retval(), n_cols, n_rows);
for(int j = 0; j < n_rows; j++) {
py_Ref row_j = py_list_getitem(argv, j);
for(int i = 0; i < n_cols; i++) {
c11_array2d__set(res, i, j, py_list_getitem(row_j, i));
}
}
return true;
}
static void register_array2d(py_Ref mod) {
py_Type type = py_newtype("array2d", tp_array2d_like, mod, NULL);
assert(type == tp_array2d);
py_bind(py_tpobject(type),
"__new__(cls, n_cols: int, n_rows: int, default=None)",
array2d__new__);
py_bindstaticmethod(type, "fromlist", array2d_fromlist_STATIC);
}
static bool array2d_view_origin(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_array2d_view* self = py_touserdata(argv);
py_newvec2i(py_retval(), self->origin);
return true;
}
static void register_array2d_view(py_Ref mod) {
py_Type type = py_newtype("array2d_view", tp_array2d_like, mod, NULL);
assert(type == tp_array2d_view);
py_bindproperty(type, "origin", array2d_view_origin, NULL);
}
/* chunked_array2d */
#define SMALLMAP_T__SOURCE
#define K c11_vec2i
#define V py_TValue*
#define NAME c11_chunked_array2d_chunks
#define less(a, b) (a._i64 < b._i64)
#define equal(a, b) (a._i64 == b._i64)
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/config.h"
#define SMALLMAP_T__HEADER
#define SMALLMAP_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_smallmap_d2f
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define partial_less(a, b) less((a).key, (b))
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef SMALLMAP_T__HEADER
/* Declaration */
typedef struct {
K key;
V value;
} KV;
typedef c11_vector NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V value);
V* METHOD(try_get)(const NAME* self, K key);
V METHOD(get)(const NAME* self, K key, V default_value);
bool METHOD(contains)(const NAME* self, K key);
bool METHOD(del)(NAME* self, K key);
void METHOD(clear)(NAME* self);
#endif
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) return &it->value;
}
return NULL;
}
V METHOD(get)(const NAME* self, K key, V default_value) {
V* p = METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
if(index != self->length) {
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef SMALLMAP_T__SOURCE
static py_TValue* c11_chunked_array2d__new_chunk(c11_chunked_array2d* self, c11_vec2i pos, py_Ref context) {
bool exists = c11_chunked_array2d_chunks__contains(&self->chunks, pos);
if(exists) {
ValueError("chunk already exists at pos (%d, %d)", pos.x, pos.y);
return NULL;
}
int chunk_numel = self->chunk_size * self->chunk_size + 1;
py_TValue* data = PK_MALLOC(sizeof(py_TValue) * chunk_numel);
data[0] = *context;
memset(&data[1], 0, sizeof(py_TValue) * (chunk_numel - 1));
c11_chunked_array2d_chunks__set(&self->chunks, pos, data);
self->last_visited.key = pos;
self->last_visited.value = data;
// init data with default value
for(int i = 1; i < chunk_numel; i++) {
data[i] = self->default_T;
}
return data;
}
static void
cpy11__divmod_int_uint(int a, int b_log2, int b_mask, int* restrict q, int* restrict r) {
if(a >= 0) {
*q = a >> b_log2;
*r = a & b_mask;
} else {
*q = -1 - ((-a - 1) >> b_log2);
*r = b_mask - ((-a - 1) & b_mask);
}
}
static void c11_chunked_array2d__world_to_chunk(c11_chunked_array2d* self,
int col,
int row,
c11_vec2i* restrict chunk_pos,
c11_vec2i* restrict local_pos) {
cpy11__divmod_int_uint(col,
self->chunk_size_log2,
self->chunk_size_mask,
&chunk_pos->x,
&local_pos->x);
cpy11__divmod_int_uint(row,
self->chunk_size_log2,
self->chunk_size_mask,
&chunk_pos->y,
&local_pos->y);
}
static py_TValue* c11_chunked_array2d__parse_col_row(c11_chunked_array2d* self,
int col,
int row,
c11_vec2i* restrict chunk_pos,
c11_vec2i* restrict local_pos) {
c11_chunked_array2d__world_to_chunk(self, col, row, chunk_pos, local_pos);
py_TValue* data;
if(self->last_visited.value != NULL && chunk_pos->_i64 == self->last_visited.key._i64) {
data = self->last_visited.value;
} else {
data = c11_chunked_array2d_chunks__get(&self->chunks, *chunk_pos, NULL);
}
if(data != NULL) {
self->last_visited.key = *chunk_pos;
self->last_visited.value = data;
}
return data;
}
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row) {
c11_vec2i chunk_pos, local_pos;
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
if(data == NULL) return NULL;
return &data[1 + local_pos.y * self->chunk_size + local_pos.x];
}
bool c11_chunked_array2d__set(c11_chunked_array2d* self, int col, int row, py_Ref value) {
c11_vec2i chunk_pos, local_pos;
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
if(data == NULL) {
if(self->auto_add_chunk) {
data = c11_chunked_array2d__new_chunk(self, chunk_pos, py_None());
if(data == NULL) return false;
} else {
return IndexError("(%d, %d) is out of bounds and !auto_add_chunk", col, row);
}
}
data[1 + local_pos.y * self->chunk_size + local_pos.x] = *value;
return true;
}
static bool chunked_array2d__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(3, tp_bool);
py_Type cls = py_totype(argv);
c11_chunked_array2d* self = py_newobject(py_retval(), cls, 0, sizeof(c11_chunked_array2d));
int chunk_size = py_toint(&argv[1]);
self->default_T = argv[2];
self->auto_add_chunk = py_tobool(&argv[3]);
c11_chunked_array2d_chunks__ctor(&self->chunks);
self->chunk_size = chunk_size;
switch(chunk_size) {
case 2: self->chunk_size_log2 = 1; break;
case 4: self->chunk_size_log2 = 2; break;
case 8: self->chunk_size_log2 = 3; break;
case 16: self->chunk_size_log2 = 4; break;
case 32: self->chunk_size_log2 = 5; break;
case 64: self->chunk_size_log2 = 6; break;
case 128: self->chunk_size_log2 = 7; break;
case 256: self->chunk_size_log2 = 8; break;
case 512: self->chunk_size_log2 = 9; break;
case 1024: self->chunk_size_log2 = 10; break;
case 2048: self->chunk_size_log2 = 11; break;
case 4096: self->chunk_size_log2 = 12; break;
default: return ValueError("invalid chunk_size: %d, not power of 2", chunk_size);
}
self->chunk_size_mask = chunk_size - 1;
memset(&self->last_visited, 0, sizeof(c11_chunked_array2d_chunks_KV));
return true;
}
static bool chunked_array2d_chunk_size(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(argv);
py_newint(py_retval(), self->chunk_size);
return true;
}
static bool chunked_array2d__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
py_Ref res = c11_chunked_array2d__get(self, pos.x, pos.y);
if(res == NULL) return IndexError("(%d, %d) is out of bounds", pos.x, pos.y);
py_assign(py_retval(), res);
return true;
}
static bool chunked_array2d__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
bool ok = c11_chunked_array2d__set(self, pos.x, pos.y, &argv[2]);
if(!ok) return false;
py_newnone(py_retval());
return true;
}
static bool chunked_array2d__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(argv);
py_Ref data = py_newtuple(py_pushtmp(), self->chunks.length);
for(int i = 0; i < self->chunks.length; i++) {
c11_chunked_array2d_chunks_KV* kv =
c11__at(c11_chunked_array2d_chunks_KV, &self->chunks, i);
py_Ref p = py_newtuple(&data[i], 2);
py_newvec2i(&p[0], kv->key); // pos
p[1] = kv->value[0]; // context
}
bool ok = py_iter(py_peek(-1));
if(!ok) return false;
py_pop();
return true;
}
static bool chunked_array2d__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(argv);
py_newint(py_retval(), self->chunks.length);
return true;
}
static bool chunked_array2d_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(argv);
c11__foreach(c11_chunked_array2d_chunks_KV, &self->chunks, p_kv) PK_FREE(p_kv->value);
c11_chunked_array2d_chunks__clear(&self->chunks);
self->last_visited.value = NULL;
py_newnone(py_retval());
return true;
}
static bool chunked_array2d_copy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(argv);
c11_chunked_array2d* res =
py_newobject(py_retval(), tp_chunked_array2d, 0, sizeof(c11_chunked_array2d));
// copy basic data
memcpy(res, self, sizeof(c11_chunked_array2d));
// invalidate last_visited cache
self->last_visited.value = NULL;
// copy chunks
memset(&res->chunks, 0, sizeof(c11_chunked_array2d_chunks));
c11_chunked_array2d_chunks__ctor(&res->chunks);
c11_vector__reserve(&res->chunks, self->chunks.capacity);
for(int i = 0; i < self->chunks.length; i++) {
c11_chunked_array2d_chunks_KV* kv =
c11__at(c11_chunked_array2d_chunks_KV, &self->chunks, i);
int chunk_numel = self->chunk_size * self->chunk_size + 1;
py_TValue* data = PK_MALLOC(sizeof(py_TValue) * chunk_numel);
memcpy(data, kv->value, sizeof(py_TValue) * chunk_numel);
// construct new KV
c11_chunked_array2d_chunks_KV new_kv;
new_kv.key = kv->key;
new_kv.value = data;
c11_vector__push(c11_chunked_array2d_chunks_KV, &res->chunks, new_kv);
}
return true;
}
static bool chunked_array2d_world_to_chunk(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
c11_vec2i chunk_pos, local_pos;
c11_chunked_array2d__world_to_chunk(self, pos.x, pos.y, &chunk_pos, &local_pos);
py_TValue* p = py_newtuple(py_retval(), 2);
py_newvec2i(&p[0], chunk_pos);
py_newvec2i(&p[1], local_pos);
return true;
}
static bool chunked_array2d_add_chunk(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
py_TValue* data = c11_chunked_array2d__new_chunk(self, pos, &argv[2]);
if(data == NULL) return false;
py_newnone(py_retval());
return true;
}
static bool chunked_array2d_remove_chunk(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
py_TValue* data = c11_chunked_array2d_chunks__get(&self->chunks, pos, NULL);
if(data != NULL) {
PK_FREE(data);
bool ok = c11_chunked_array2d_chunks__del(&self->chunks, pos);
assert(ok);
self->last_visited.value = NULL;
py_newbool(py_retval(), ok);
} else {
py_newbool(py_retval(), false);
}
return true;
}
static bool chunked_array2d_move_chunk(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
PY_CHECK_ARG_TYPE(2, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i src = py_tovec2i(&argv[1]);
c11_vec2i dst = py_tovec2i(&argv[2]);
py_TValue* src_data = c11_chunked_array2d_chunks__get(&self->chunks, src, NULL);
py_TValue* dst_data = c11_chunked_array2d_chunks__get(&self->chunks, dst, NULL);
if(src_data == NULL || dst_data != NULL) {
py_newbool(py_retval(), false);
return true;
}
c11_chunked_array2d_chunks__del(&self->chunks, src);
c11_chunked_array2d_chunks__set(&self->chunks, dst, src_data);
self->last_visited.value = NULL;
py_newbool(py_retval(), true);
return true;
}
static bool chunked_array2d_get_context(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(argv);
c11_vec2i pos = py_tovec2i(&argv[1]);
py_TValue* data = c11_chunked_array2d_chunks__get(&self->chunks, pos, NULL);
if(data == NULL) {
return IndexError("no chunk found at (%d, %d)", pos.x, pos.y);
} else {
py_assign(py_retval(), &data[0]);
}
return true;
}
void c11_chunked_array2d__dtor(c11_chunked_array2d* self) {
c11__foreach(c11_chunked_array2d_chunks_KV, &self->chunks, p_kv) PK_FREE(p_kv->value);
c11_chunked_array2d_chunks__dtor(&self->chunks);
}
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack) {
c11_chunked_array2d* self = ud;
pk__mark_value(&self->default_T);
int chunk_numel = self->chunk_size * self->chunk_size + 1;
for(int i = 0; i < self->chunks.length; i++) {
py_TValue* data = c11__getitem(c11_chunked_array2d_chunks_KV, &self->chunks, i).value;
for(int j = 0; j < chunk_numel; j++) {
pk__mark_value(data + j);
}
}
}
static bool chunked_array2d_view(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_chunked_array2d* self = py_touserdata(&argv[0]);
if(self->chunks.length == 0) { return ValueError("chunked_array2d is empty"); }
int min_chunk_x = INT_MAX;
int min_chunk_y = INT_MAX;
int max_chunk_x = INT_MIN;
int max_chunk_y = INT_MIN;
for(int i = 0; i < self->chunks.length; i++) {
c11_vec2i chunk_pos = c11__getitem(c11_chunked_array2d_chunks_KV, &self->chunks, i).key;
min_chunk_x = c11__min(min_chunk_x, chunk_pos.x);
min_chunk_y = c11__min(min_chunk_y, chunk_pos.y);
max_chunk_x = c11__max(max_chunk_x, chunk_pos.x);
max_chunk_y = c11__max(max_chunk_y, chunk_pos.y);
}
int start_col = min_chunk_x * self->chunk_size;
int start_row = min_chunk_y * self->chunk_size;
int width = (max_chunk_x - min_chunk_x + 1) * self->chunk_size;
int height = (max_chunk_y - min_chunk_y + 1) * self->chunk_size;
return _chunked_array2d_view(py_retval(), argv, self, start_col, start_row, width, height);
}
static bool chunked_array2d_view_rect(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
PY_CHECK_ARG_TYPE(2, tp_int);
PY_CHECK_ARG_TYPE(3, tp_int);
c11_chunked_array2d* self = py_touserdata(&argv[0]);
c11_vec2i pos = py_tovec2i(&argv[1]);
int width = py_toint(&argv[2]);
int height = py_toint(&argv[3]);
return _chunked_array2d_view(py_retval(), argv, self, pos.x, pos.y, width, height);
}
static bool chunked_array2d_view_chunk(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
c11_chunked_array2d* self = py_touserdata(&argv[0]);
c11_vec2i chunk_pos = py_tovec2i(&argv[1]);
int start_col = chunk_pos.x * self->chunk_size;
int start_row = chunk_pos.y * self->chunk_size;
return _chunked_array2d_view(py_retval(),
argv,
self,
start_col,
start_row,
self->chunk_size,
self->chunk_size);
}
static bool chunked_array2d_view_chunks(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
PY_CHECK_ARG_TYPE(1, tp_vec2i);
PY_CHECK_ARG_TYPE(2, tp_int);
PY_CHECK_ARG_TYPE(3, tp_int);
c11_chunked_array2d* self = py_touserdata(&argv[0]);
c11_vec2i chunk_pos = py_tovec2i(&argv[1]);
int width = py_toint(&argv[2]) * self->chunk_size;
int height = py_toint(&argv[3]) * self->chunk_size;
int start_col = chunk_pos.x * self->chunk_size;
int start_row = chunk_pos.y * self->chunk_size;
return _chunked_array2d_view(py_retval(), argv, self, start_col, start_row, width, height);
}
static void register_chunked_array2d(py_Ref mod) {
py_Type type =
py_newtype("chunked_array2d", tp_object, mod, (py_Dtor)c11_chunked_array2d__dtor);
assert(type == tp_chunked_array2d);
py_bind(py_tpobject(type),
"__new__(cls, chunk_size, default=None, auto_add_chunk=True)",
chunked_array2d__new__);
py_bindproperty(type, "chunk_size", chunked_array2d_chunk_size, NULL);
py_bindmagic(type, __getitem__, chunked_array2d__getitem__);
py_bindmagic(type, __setitem__, chunked_array2d__setitem__);
py_bindmagic(type, __iter__, chunked_array2d__iter__);
py_bindmagic(type, __len__, chunked_array2d__len__);
py_bindmethod(type, "clear", chunked_array2d_clear);
py_bindmethod(type, "copy", chunked_array2d_copy);
py_bindmethod(type, "world_to_chunk", chunked_array2d_world_to_chunk);
py_bindmethod(type, "add_chunk", chunked_array2d_add_chunk);
py_bindmethod(type, "remove_chunk", chunked_array2d_remove_chunk);
py_bindmethod(type, "move_chunk", chunked_array2d_move_chunk);
py_bindmethod(type, "get_context", chunked_array2d_get_context);
py_bindmethod(type, "view", chunked_array2d_view);
py_bindmethod(type, "view_rect", chunked_array2d_view_rect);
py_bindmethod(type, "view_chunk", chunked_array2d_view_chunk);
py_bindmethod(type, "view_chunks", chunked_array2d_view_chunks);
}
void pk__add_module_array2d() {
py_GlobalRef mod = py_newmodule("array2d");
register_array2d_like(mod);
register_array2d_like_iterator(mod);
register_array2d(mod);
register_array2d_view(mod);
register_chunked_array2d(mod);
}
void py_newarray2d(py_OutRef out, int width, int height) { c11_newarray2d(out, width, height); }
int py_array2d_getwidth(py_Ref self) {
assert(self->type == tp_array2d);
c11_array2d* ud = py_touserdata(self);
return ud->header.n_cols;
}
int py_array2d_getheight(py_Ref self) {
assert(self->type == tp_array2d);
c11_array2d* ud = py_touserdata(self);
return ud->header.n_rows;
}
py_ObjectRef py_array2d_getitem(py_Ref self, int x, int y) {
assert(self->type == tp_array2d);
c11_array2d* ud = py_touserdata(self);
return c11_array2d__get(ud, x, y);
}
void py_array2d_setitem(py_Ref self, int x, int y, py_Ref value) {
assert(self->type == tp_array2d);
c11_array2d* ud = py_touserdata(self);
c11_array2d__set(ud, x, y, value);
}
// src/modules\base64.c
#include <limits.h>
// https://github.com/zhicheng/base64/blob/master/base64.c
const char BASE64_PAD = '=';
const char BASE64DE_FIRST = '+';
const char BASE64DE_LAST = 'z';
/* BASE 64 encode table */
const char base64en[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
};
/* ASCII order for BASE 64 decode, 255 in unused character */
const unsigned char base64de[] = {
/* nul, soh, stx, etx, eot, enq, ack, bel, */
255, 255, 255, 255, 255, 255, 255, 255,
/* bs, ht, nl, vt, np, cr, so, si, */
255, 255, 255, 255, 255, 255, 255, 255,
/* dle, dc1, dc2, dc3, dc4, nak, syn, etb, */
255, 255, 255, 255, 255, 255, 255, 255,
/* can, em, sub, esc, fs, gs, rs, us, */
255, 255, 255, 255, 255, 255, 255, 255,
/* sp, '!', '"', '#', '$', '%', '&', ''', */
255, 255, 255, 255, 255, 255, 255, 255,
/* '(', ')', '*', '+', ',', '-', '.', '/', */
255, 255, 255, 62, 255, 255, 255, 63,
/* '0', '1', '2', '3', '4', '5', '6', '7', */
52, 53, 54, 55, 56, 57, 58, 59,
/* '8', '9', ':', ';', '<', '=', '>', '?', */
60, 61, 255, 255, 255, 255, 255, 255,
/* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
255, 0, 1, 2, 3, 4, 5, 6,
/* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
7, 8, 9, 10, 11, 12, 13, 14,
/* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
15, 16, 17, 18, 19, 20, 21, 22,
/* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
23, 24, 25, 255, 255, 255, 255, 255,
/* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
255, 26, 27, 28, 29, 30, 31, 32,
/* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
33, 34, 35, 36, 37, 38, 39, 40,
/* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
41, 42, 43, 44, 45, 46, 47, 48,
/* 'x', 'y', 'z', '{', '|', '}', '~', del, */
49, 50, 51, 255, 255, 255, 255, 255
};
static unsigned int
base64_encode(const unsigned char *in, unsigned int inlen, char *out)
{
int s;
unsigned int i;
unsigned int j;
unsigned char c;
unsigned char l;
s = 0;
l = 0;
for (i = j = 0; i < inlen; i++) {
c = in[i];
switch (s) {
case 0:
s = 1;
out[j++] = base64en[(c >> 2) & 0x3F];
break;
case 1:
s = 2;
out[j++] = base64en[((l & 0x3) << 4) | ((c >> 4) & 0xF)];
break;
case 2:
s = 0;
out[j++] = base64en[((l & 0xF) << 2) | ((c >> 6) & 0x3)];
out[j++] = base64en[c & 0x3F];
break;
}
l = c;
}
switch (s) {
case 1:
out[j++] = base64en[(l & 0x3) << 4];
out[j++] = BASE64_PAD;
out[j++] = BASE64_PAD;
break;
case 2:
out[j++] = base64en[(l & 0xF) << 2];
out[j++] = BASE64_PAD;
break;
}
out[j] = 0;
return j;
}
static unsigned int
base64_decode(const char *in, unsigned int inlen, unsigned char *out)
{
unsigned int i;
unsigned int j;
unsigned char c;
if (inlen & 0x3) {
return 0;
}
for (i = j = 0; i < inlen; i++) {
if (in[i] == BASE64_PAD) {
break;
}
if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST) {
return 0;
}
c = base64de[(unsigned char)in[i]];
if (c == 255) {
return 0;
}
switch (i & 0x3) {
case 0:
out[j] = (c << 2) & 0xFF;
break;
case 1:
out[j++] |= (c >> 4) & 0x3;
out[j] = (c & 0xF) << 4;
break;
case 2:
out[j++] |= (c >> 2) & 0xF;
out[j] = (c & 0x3) << 6;
break;
case 3:
out[j++] |= c;
break;
}
}
return j;
}
static bool base64_b64encode(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_bytes);
int src_size;
unsigned char* src_data = py_tobytes(argv, &src_size);
unsigned char* dst_data = py_newbytes(py_retval(), src_size * 4 / 3 + 4);
int size = base64_encode(src_data, src_size, (char*)dst_data);
py_bytes_resize(py_retval(), size);
return true;
}
static bool base64_b64decode(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int src_size;
void* src_data;
if(py_istype(argv, tp_str)) {
c11_sv sv = py_tosv(argv);
src_data = (void*)sv.data;
src_size = sv.size;
} else if(py_istype(argv, tp_bytes)) {
src_data = py_tobytes(argv, &src_size);
} else {
return TypeError("expect bytes or str, got %t", argv->type);
}
unsigned char* dst_data = py_newbytes(py_retval(), src_size);
int size = base64_decode((const char*)src_data, src_size, dst_data);
py_bytes_resize(py_retval(), size);
return true;
}
void pk__add_module_base64(){
py_GlobalRef mod = py_newmodule("base64");
py_bindfunc(mod, "b64encode", base64_b64encode);
py_bindfunc(mod, "b64decode", base64_b64decode);
}
// src/modules\builtins.c
static bool builtins_exit(int argc, py_Ref argv) {
int code = 0;
if(argc > 1) return TypeError("exit() takes at most 1 argument");
if(argc == 1) {
PY_CHECK_ARG_TYPE(0, tp_int);
code = py_toint(argv);
}
exit(code);
return false;
}
static bool builtins_input(int argc, py_Ref argv) {
if(argc > 1) return TypeError("input() takes at most 1 argument");
const char* prompt = "";
if(argc == 1) {
if(!py_checkstr(argv)) return false;
prompt = py_tostr(argv);
}
py_callbacks()->print(prompt);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
while(true) {
int c = py_callbacks()->getchr();
if(c == '\n' || c == '\r') break;
if(c == EOF) break;
c11_sbuf__write_char(&buf, c);
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool builtins_repr(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_repr(argv);
}
static bool builtins_len(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_len(argv);
}
static bool builtins_hex(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
py_i64 val = py_toint(argv);
if(val == 0) {
py_newstr(py_retval(), "0x0");
return true;
}
c11_sbuf ss;
c11_sbuf__ctor(&ss);
if(val < 0) {
c11_sbuf__write_char(&ss, '-');
val = -val;
}
c11_sbuf__write_cstr(&ss, "0x");
bool non_zero = true;
for(int i = 56; i >= 0; i -= 8) {
unsigned char cpnt = (val >> i) & 0xff;
c11_sbuf__write_hex(&ss, cpnt, non_zero);
if(cpnt != 0) non_zero = false;
}
c11_sbuf__py_submit(&ss, py_retval());
return true;
}
static bool builtins_bin(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
py_i64 val = py_toint(argv);
if(val == 0) {
py_newstr(py_retval(), "0b0");
return true;
}
c11_sbuf ss;
c11_sbuf__ctor(&ss);
if(val < 0) {
c11_sbuf__write_char(&ss, '-');
val = -val;
}
c11_sbuf__write_cstr(&ss, "0b");
bool non_zero = true;
for(int i = 63; i >= 0; i--) {
unsigned char bit = (val >> i) & 1;
if(bit != 0) non_zero = false;
if(!non_zero) c11_sbuf__write_char(&ss, bit ? '1' : '0');
}
c11_sbuf__py_submit(&ss, py_retval());
return true;
}
static bool builtins_iter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_iter(argv);
}
static bool builtins_next(int argc, py_Ref argv) {
if(argc == 0 || argc > 2) return TypeError("next() takes 1 or 2 arguments");
int res = py_next(argv);
if(res == -1) return false;
if(res) return true;
if(argc == 1) {
// StopIteration stored in py_retval()
return py_raise(py_retval());
} else {
py_assign(py_retval(), py_arg(1));
return true;
}
}
static bool builtins_hash(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 val;
if(!py_hash(argv, &val)) return false;
py_newint(py_retval(), val);
return true;
}
static bool builtins_abs(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return pk_callmagic(__abs__, 1, argv);
}
static bool builtins_divmod(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
return pk_callmagic(__divmod__, 2, argv);
}
static bool builtins_round(int argc, py_Ref argv) {
py_i64 ndigits;
if(argc == 1) {
ndigits = -1;
} else if(argc == 2) {
PY_CHECK_ARG_TYPE(1, tp_int);
ndigits = py_toint(py_arg(1));
if(ndigits < 0) return ValueError("ndigits should be non-negative");
} else {
return TypeError("round() takes 1 or 2 arguments");
}
if(argv->type == tp_int) {
py_assign(py_retval(), py_arg(0));
return true;
} else if(argv->type == tp_float) {
py_f64 x = py_tofloat(py_arg(0));
py_f64 offset = x >= 0 ? 0.5 : -0.5;
if(ndigits == -1) {
py_newint(py_retval(), (py_i64)(x + offset));
return true;
}
// py_f64 factor = dmath_exp10(ndigits);
py_f64 factor = 1.0;
for(int i = 0; i < ndigits; i++) factor *= 10.0;
py_newfloat(py_retval(), (py_i64)(x * factor + offset) / factor);
return true;
}
return pk_callmagic(__round__, argc, argv);
}
static bool builtins_print(int argc, py_Ref argv) {
// print(*args, sep=' ', end='\n', flush=False)
py_TValue* args = py_tuple_data(argv);
int length = py_tuple_len(argv);
PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_str);
PY_CHECK_ARG_TYPE(3, tp_bool);
c11_sv sep = py_tosv(py_arg(1));
c11_sv end = py_tosv(py_arg(2));
bool flush = py_tobool(py_arg(3));
c11_sbuf buf;
c11_sbuf__ctor(&buf);
for(int i = 0; i < length; i++) {
if(i > 0) c11_sbuf__write_sv(&buf, sep);
if(!py_str(&args[i])) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
}
c11_sbuf__write_sv(&buf, end);
c11_string* res = c11_sbuf__submit(&buf);
py_callbacks()->print(res->data);
if(flush) py_callbacks()->flush();
c11_string__delete(res);
py_newnone(py_retval());
return true;
}
static bool builtins_isinstance(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(py_istuple(py_arg(1))) {
int length = py_tuple_len(py_arg(1));
for(int i = 0; i < length; i++) {
py_Ref item = py_tuple_getitem(py_arg(1), i);
if(!py_checktype(item, tp_type)) return false;
if(py_isinstance(py_arg(0), py_totype(item))) {
py_newbool(py_retval(), true);
return true;
}
}
py_newbool(py_retval(), false);
return true;
}
if(!py_checktype(py_arg(1), tp_type)) return false;
py_newbool(py_retval(), py_isinstance(py_arg(0), py_totype(py_arg(1))));
return true;
}
static bool builtins_issubclass(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(!py_checktype(py_arg(0), tp_type)) return false;
if(!py_checktype(py_arg(1), tp_type)) return false;
py_newbool(py_retval(), py_issubclass(py_totype(py_arg(0)), py_totype(py_arg(1))));
return true;
}
static bool builtins_callable(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
bool res = py_callable(py_arg(0));
py_newbool(py_retval(), res);
return true;
}
static bool builtins_getattr(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
if(argc == 2) {
return py_getattr(py_arg(0), name);
} else if(argc == 3) {
bool ok = py_getattr(py_arg(0), name);
if(!ok && py_matchexc(tp_AttributeError)) {
py_clearexc(NULL);
py_assign(py_retval(), py_arg(2));
return true; // default value
}
return ok;
} else {
return TypeError("getattr() expected 2 or 3 arguments");
}
return true;
}
static bool builtins_setattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_newnone(py_retval());
return py_setattr(py_arg(0), name, py_arg(2));
}
static bool builtins_hasattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
bool ok = py_getattr(py_arg(0), name);
if(ok) {
py_newbool(py_retval(), true);
return true;
}
if(py_matchexc(tp_AttributeError)) {
py_clearexc(NULL);
py_newbool(py_retval(), false);
return true;
}
return false;
}
static bool builtins_delattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1)));
py_newnone(py_retval());
return py_delattr(py_arg(0), name);
}
static bool builtins_chr(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
uint32_t val = py_toint(py_arg(0));
// convert to utf-8
char utf8[4];
int len = c11__u32_to_u8(val, utf8);
if(len == -1) return ValueError("invalid unicode code point: %d", val);
py_newstrv(py_retval(), (c11_sv){utf8, len});
return true;
}
static bool builtins_ord(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv sv = py_tosv(py_arg(0));
if(c11_sv__u8_length(sv) != 1) {
return TypeError("ord() expected a character, but string of length %d found",
c11_sv__u8_length(sv));
}
int u8bytes = c11__u8_header(sv.data[0], true);
if(u8bytes == 0) return ValueError("invalid utf-8 char: %c", sv.data[0]);
int value = c11__u8_value(u8bytes, sv.data);
py_newint(py_retval(), value);
return true;
}
static bool builtins_id(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(argv->is_ptr) {
py_newint(py_retval(), (intptr_t)argv->_obj);
} else {
py_newnone(py_retval());
}
return true;
}
static bool builtins_globals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_newglobals(py_retval());
return true;
}
static bool builtins_locals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_newlocals(py_retval());
return true;
}
static void pk_push_special_locals() {
py_Frame* frame = pk_current_vm->top_frame;
if(!frame) {
py_pushnil();
return;
}
if(frame->is_locals_special) {
py_push(frame->locals);
} else {
py_StackRef out = py_pushtmp();
out->type = tp_locals;
out->is_ptr = false;
out->extra = 0;
// this is a weak reference
// which will expire when the frame is destroyed
out->_ptr = frame;
}
}
static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {
switch(argc) {
case 1: {
py_newglobals(py_pushtmp());
pk_push_special_locals();
break;
}
case 2: {
// globals
if(py_isnone(py_arg(1))) {
py_newglobals(py_pushtmp());
} else {
py_push(py_arg(1));
}
// locals
py_pushnil();
break;
}
case 3: {
// globals
if(py_isnone(py_arg(1))) {
py_newglobals(py_pushtmp());
} else {
py_push(py_arg(1));
}
// locals
if(py_isnone(py_arg(2))) {
py_pushnil();
} else {
py_push(py_arg(2));
}
break;
}
default: return TypeError("%s() takes at most 3 arguments", title);
}
if(py_isstr(argv)) {
bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
if(!ok) return false;
py_push(py_retval());
} else if(py_istype(argv, tp_code)) {
py_push(argv);
} else {
return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type);
}
py_Frame* frame = pk_current_vm->top_frame;
// [globals, locals, code]
CodeObject* code = py_touserdata(py_peek(-1));
if(code->src->is_dynamic) {
bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
py_shrink(3);
return ok;
} else {
if(argc != 1) {
return ValueError(
"code object is not dynamic, `globals` and `locals` must not be specified");
}
bool ok = pk_exec(code, frame ? frame->module : NULL);
py_shrink(3);
return ok;
}
}
static bool builtins_exec(int argc, py_Ref argv) {
bool ok = _builtins_execdyn("exec", argc, argv, EXEC_MODE);
py_newnone(py_retval());
return ok;
}
static bool builtins_eval(int argc, py_Ref argv) {
return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
}
static bool builtins_compile(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
for(int i = 0; i < 3; i++) {
if(!py_checktype(py_arg(i), tp_str)) return false;
}
const char* source = py_tostr(py_arg(0));
const char* filename = py_tostr(py_arg(1));
const char* mode = py_tostr(py_arg(2));
enum py_CompileMode compile_mode;
if(strcmp(mode, "exec") == 0) {
compile_mode = EXEC_MODE;
} else if(strcmp(mode, "eval") == 0) {
compile_mode = EVAL_MODE;
} else if(strcmp(mode, "single") == 0) {
compile_mode = SINGLE_MODE;
} else {
return ValueError("compile() mode must be 'exec', 'eval', or 'single'");
}
return py_compile(source, filename, compile_mode, true);
}
static bool builtins__import__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0));
if(path[0] == '.') return ValueError("relative import not allowed here");
int res = py_import(path);
if(res == -1) return false;
if(res) return true;
return ImportError("module '%s' not found", path);
}
static bool NoneType__repr__(int argc, py_Ref argv) {
py_newstr(py_retval(), "None");
return true;
}
static bool ellipsis__repr__(int argc, py_Ref argv) {
py_newstr(py_retval(), "...");
return true;
}
static bool NotImplementedType__repr__(int argc, py_Ref argv) {
py_newstr(py_retval(), "NotImplemented");
return true;
}
py_GlobalRef pk_builtins__register() {
py_GlobalRef builtins = py_newmodule("builtins");
py_bindfunc(builtins, "exit", builtins_exit);
py_bindfunc(builtins, "input", builtins_input);
py_bindfunc(builtins, "repr", builtins_repr);
py_bindfunc(builtins, "len", builtins_len);
py_bindfunc(builtins, "hex", builtins_hex);
py_bindfunc(builtins, "bin", builtins_bin);
py_bindfunc(builtins, "iter", builtins_iter);
py_bindfunc(builtins, "next", builtins_next);
py_bindfunc(builtins, "hash", builtins_hash);
py_bindfunc(builtins, "abs", builtins_abs);
py_bindfunc(builtins, "divmod", builtins_divmod);
py_bindfunc(builtins, "round", builtins_round);
py_bind(builtins, "print(*args, sep=' ', end='\\n', flush=False)", builtins_print);
py_bindfunc(builtins, "isinstance", builtins_isinstance);
py_bindfunc(builtins, "issubclass", builtins_issubclass);
py_bindfunc(builtins, "callable", builtins_callable);
py_bindfunc(builtins, "getattr", builtins_getattr);
py_bindfunc(builtins, "setattr", builtins_setattr);
py_bindfunc(builtins, "hasattr", builtins_hasattr);
py_bindfunc(builtins, "delattr", builtins_delattr);
py_bindfunc(builtins, "chr", builtins_chr);
py_bindfunc(builtins, "ord", builtins_ord);
py_bindfunc(builtins, "id", builtins_id);
py_bindfunc(builtins, "globals", builtins_globals);
py_bindfunc(builtins, "locals", builtins_locals);
py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "eval", builtins_eval);
py_bindfunc(builtins, "compile", builtins_compile);
py_bindfunc(builtins, "__import__", builtins__import__);
// some patches
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
py_setdict(py_tpobject(tp_NoneType), __hash__, py_None());
py_bindmagic(tp_ellipsis, __repr__, ellipsis__repr__);
py_setdict(py_tpobject(tp_ellipsis), __hash__, py_None());
py_bindmagic(tp_NotImplementedType, __repr__, NotImplementedType__repr__);
py_setdict(py_tpobject(tp_NotImplementedType), __hash__, py_None());
return builtins;
}
void function__gc_mark(void* ud, c11_vector* p_stack) {
Function* func = ud;
pk__mark_value(&func->globals);
if(func->closure) {
NameDict* dict = func->closure;
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
pk__mark_value(&kv->value);
}
}
FuncDecl__gc_mark(func->decl, p_stack);
}
static bool function__doc__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Function* func = py_touserdata(py_arg(0));
if(func->decl->docstring) {
py_newstr(py_retval(), func->decl->docstring);
} else {
py_newnone(py_retval());
}
return true;
}
static bool function__name__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Function* func = py_touserdata(py_arg(0));
py_newstr(py_retval(), func->decl->code.name->data);
return true;
}
static bool function__repr__(int argc, py_Ref argv) {
// <function f at 0x10365b9c0>
PY_CHECK_ARGC(1);
Function* func = py_touserdata(py_arg(0));
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, "<function ");
c11_sbuf__write_cstr(&buf, func->decl->code.name->data);
c11_sbuf__write_cstr(&buf, " at ");
c11_sbuf__write_ptr(&buf, func);
c11_sbuf__write_char(&buf, '>');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
py_Type pk_function__register() {
py_Type type =
pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
py_bindproperty(type, "__doc__", function__doc__, NULL);
py_bindproperty(type, "__name__", function__name__, NULL);
py_bindmagic(type, __repr__, function__repr__);
return type;
}
static bool nativefunc__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_newstr(py_retval(), "<nativefunc object>");
return true;
}
py_Type pk_nativefunc__register() {
py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __repr__, nativefunc__repr__);
return type;
}
static bool super__new__(int argc, py_Ref argv) {
py_Type class_arg = 0;
py_Frame* frame = pk_current_vm->top_frame;
py_Ref self_arg = NULL;
if(argc == 1) {
// super()
if(!frame->is_locals_special) {
py_TValue* callable = frame->p0;
if(callable->type == tp_boundmethod) callable = py_getslot(frame->p0, 1);
if(callable->type == tp_function) {
Function* func = py_touserdata(callable);
if(func->clazz != NULL) {
class_arg = ((py_TypeInfo*)PyObject__userdata(func->clazz))->index;
if(frame->co->nlocals > 0) { self_arg = &frame->locals[0]; }
}
}
}
if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments");
if(self_arg->type == tp_type) {
// f(cls, ...)
class_arg = pk_typeinfo(class_arg)->base;
if(class_arg == 0) return RuntimeError("super(): base class is invalid");
py_assign(py_retval(), py_tpobject(class_arg));
return true;
}
} else if(argc == 3) {
// super(type[T], obj)
PY_CHECK_ARG_TYPE(1, tp_type);
class_arg = py_totype(py_arg(1));
self_arg = py_arg(2);
if(!py_isinstance(self_arg, class_arg)) {
return TypeError("super(type, obj): obj must be an instance of type");
}
} else {
return TypeError("super() takes 0 or 2 arguments");
}
class_arg = pk_typeinfo(class_arg)->base;
if(class_arg == 0) return RuntimeError("super(): base class is invalid");
py_Type* p_class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type));
*p_class_arg = class_arg;
py_setslot(py_retval(), 0, self_arg);
return true;
}
py_Type pk_super__register() {
py_Type type = pk_newtype("super", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, super__new__);
return type;
}
// src/modules\colorcvt.c
// https://bottosson.github.io/posts/gamutclipping/#oklab-to-linear-srgb-conversion
// clang-format off
static c11_vec3 linear_srgb_to_oklab(c11_vec3 c)
{
double l = 0.4122214708 * c.x + 0.5363325363 * c.y + 0.0514459929 * c.z;
double m = 0.2119034982 * c.x + 0.6806995451 * c.y + 0.1073969566 * c.z;
double s = 0.0883024619 * c.x + 0.2817188376 * c.y + 0.6299787005 * c.z;
double l_ = dmath_cbrt(l);
double m_ = dmath_cbrt(m);
double s_ = dmath_cbrt(s);
return (c11_vec3){{
0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,
1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,
0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,
}};
}
static c11_vec3 oklab_to_linear_srgb(c11_vec3 c)
{
double l_ = c.x + 0.3963377774 * c.y + 0.2158037573 * c.z;
double m_ = c.x - 0.1055613458 * c.y - 0.0638541728 * c.z;
double s_ = c.x - 0.0894841775 * c.y - 1.2914855480 * c.z;
double l = l_ * l_ * l_;
double m = m_ * m_ * m_;
double s = s_ * s_ * s_;
return (c11_vec3){{
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
}};
}
// clang-format on
static double _gamma_correct_inv(double x) {
return (x <= 0.04045) ? (x / 12.92) : dmath_pow((x + 0.055) / 1.055, 2.4);
}
static double _gamma_correct(double x) {
return (x <= 0.0031308) ? (12.92 * x) : (1.055 * dmath_pow(x, 1.0 / 2.4) - 0.055);
}
static c11_vec3 srgb_to_linear_srgb(c11_vec3 c) {
c.x = _gamma_correct_inv(c.x);
c.y = _gamma_correct_inv(c.y);
c.z = _gamma_correct_inv(c.z);
return c;
}
static c11_vec3 linear_srgb_to_srgb(c11_vec3 c) {
c.x = _gamma_correct(c.x);
c.y = _gamma_correct(c.y);
c.z = _gamma_correct(c.z);
return c;
}
static c11_vec3 _oklab_to_oklch(c11_vec3 c) {
c11_vec3 res;
res.x = c.x;
res.y = dmath_sqrt(c.y * c.y + c.z * c.z);
res.z = dmath_fmod(dmath_atan2(c.z, c.y), 2 * DMATH_PI);
res.z = res.z * DMATH_RAD2DEG;
return res;
}
static c11_vec3 _oklch_to_oklab(c11_vec3 c) {
c11_vec3 res;
res.x = c.x;
res.y = c.y * dmath_cos(c.z * DMATH_DEG2RAD);
res.z = c.y * dmath_sin(c.z * DMATH_DEG2RAD);
return res;
}
static c11_vec3 linear_srgb_to_oklch(c11_vec3 c) {
return _oklab_to_oklch(linear_srgb_to_oklab(c));
}
static bool _is_valid_srgb(c11_vec3 c) {
return c.x >= 0.0f && c.x <= 1.0f && c.y >= 0.0f && c.y <= 1.0f && c.z >= 0.0f && c.z <= 1.0f;
}
static c11_vec3 oklch_to_linear_srgb(c11_vec3 c) {
c11_vec3 candidate = oklab_to_linear_srgb(_oklch_to_oklab(c));
if(_is_valid_srgb(candidate)) return candidate;
// try with chroma = 0
c11_vec3 clamped = {
{c.x, 0.0f, c.z}
};
// if not even chroma = 0 is displayable
// fall back to RGB clamping
candidate = oklab_to_linear_srgb(_oklch_to_oklab(clamped));
if(!_is_valid_srgb(candidate)) {
candidate.x = dmath_fmax(0.0, dmath_fmin(1.0, candidate.x));
candidate.y = dmath_fmax(0.0, dmath_fmin(1.0, candidate.y));
candidate.z = dmath_fmax(0.0, dmath_fmin(1.0, candidate.z));
return candidate;
}
// By this time we know chroma = 0 is displayable and our current chroma is not.
// Find the displayable chroma through the bisection method.
float start = 0.0f;
float end = c.y;
float range[2] = {0.0f, 0.4f};
float resolution = (range[1] - range[0]) / dmath_pow(2, 13);
float _last_good_c = clamped.y;
while(end - start > resolution) {
clamped.y = start + (end - start) * 0.5f;
candidate = oklab_to_linear_srgb(_oklch_to_oklab(clamped));
if(_is_valid_srgb(candidate)) {
_last_good_c = clamped.y;
start = clamped.y;
} else {
end = clamped.y;
}
}
candidate = oklab_to_linear_srgb(_oklch_to_oklab(clamped));
if(_is_valid_srgb(candidate)) return candidate;
clamped.y = _last_good_c;
return oklab_to_linear_srgb(_oklch_to_oklab(clamped));
}
// https://github.com/python/cpython/blob/3.13/Lib/colorsys.py
static c11_vec3 srgb_to_hsv(c11_vec3 c) {
float r = c.x;
float g = c.y;
float b = c.z;
float maxc = dmath_fmax(r, dmath_fmax(g, b));
float minc = dmath_fmin(r, dmath_fmin(g, b));
float v = maxc;
if(minc == maxc) {
return (c11_vec3){
{0.0f, 0.0f, v}
};
}
float s = (maxc - minc) / maxc;
float rc = (maxc - r) / (maxc - minc);
float gc = (maxc - g) / (maxc - minc);
float bc = (maxc - b) / (maxc - minc);
float h;
if(r == maxc) {
h = bc - gc;
} else if(g == maxc) {
h = 2.0f + rc - bc;
} else {
h = 4.0f + gc - rc;
}
h = dmath_fmod(h / 6.0, 1.0);
return (c11_vec3){
{h, s, v}
};
}
static c11_vec3 hsv_to_srgb(c11_vec3 c) {
float h = c.x;
float s = c.y;
float v = c.z;
if(s == 0.0f) {
return (c11_vec3){
{v, v, v}
};
}
int i = (int)(h * 6.0f);
float f = (h * 6.0f) - i;
float p = v * (1.0f - s);
float q = v * (1.0f - s * f);
float t = v * (1.0f - s * (1.0f - f));
i = i % 6;
switch(i) {
// clang-format off
case 0: return (c11_vec3){{v, t, p}};
case 1: return (c11_vec3){{q, v, p}};
case 2: return (c11_vec3){{p, v, t}};
case 3: return (c11_vec3){{p, q, v}};
case 4: return (c11_vec3){{t, p, v}};
case 5: return (c11_vec3){{v, p, q}};
// clang-format on
default: c11__unreachable();
}
}
#define DEF_VEC3_WRAPPER(F) \
static bool colorcvt_##F(int argc, py_Ref argv); \
static bool colorcvt_##F(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
PY_CHECK_ARG_TYPE(0, tp_vec3); \
c11_vec3 c = py_tovec3(argv); \
py_newvec3(py_retval(), F(c)); \
return true; \
}
DEF_VEC3_WRAPPER(linear_srgb_to_srgb)
DEF_VEC3_WRAPPER(srgb_to_linear_srgb)
DEF_VEC3_WRAPPER(srgb_to_hsv)
DEF_VEC3_WRAPPER(hsv_to_srgb)
DEF_VEC3_WRAPPER(oklch_to_linear_srgb)
DEF_VEC3_WRAPPER(linear_srgb_to_oklch)
void pk__add_module_colorcvt() {
py_Ref mod = py_newmodule("colorcvt");
py_bindfunc(mod, "linear_srgb_to_srgb", colorcvt_linear_srgb_to_srgb);
py_bindfunc(mod, "srgb_to_linear_srgb", colorcvt_srgb_to_linear_srgb);
py_bindfunc(mod, "srgb_to_hsv", colorcvt_srgb_to_hsv);
py_bindfunc(mod, "hsv_to_srgb", colorcvt_hsv_to_srgb);
py_bindfunc(mod, "oklch_to_linear_srgb", colorcvt_oklch_to_linear_srgb);
py_bindfunc(mod, "linear_srgb_to_oklch", colorcvt_linear_srgb_to_oklch);
}
#undef DEF_VEC3_WRAPPER
// src/modules\conio.c
#if PY_SYS_PLATFORM == 0
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <conio.h>
#undef WIN32_LEAN_AND_MEAN
#elif PY_SYS_PLATFORM == 3 || PY_SYS_PLATFORM == 5
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
// 保存原始终端设置
static struct termios orig_termios;
static bool orig_termios_set;
// 还原终端设置
static void reset_terminal_mode() { tcsetattr(0, TCSANOW, &orig_termios); }
// 设置终端为非阻塞模式
static void set_conio_terminal_mode_if_needed() {
if(orig_termios_set) return;
struct termios new_termios;
// 获取当前终端设置
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
// 禁用缓冲和回显
new_termios.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &new_termios);
atexit(reset_terminal_mode);
orig_termios_set = true;
}
// 检查是否有按键按下
int _kbhit() {
set_conio_terminal_mode_if_needed();
struct termios term;
int oldf;
int ch;
int old_flags;
// 获取终端设置
tcgetattr(0, &term);
oldf = term.c_lflag;
term.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &term);
// 设置文件描述符为非阻塞
old_flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, old_flags | O_NONBLOCK);
// 检查是否有输入
ch = getchar();
// 还原文件描述符设置
fcntl(STDIN_FILENO, F_SETFL, old_flags);
// 还原终端设置
term.c_lflag = oldf;
tcsetattr(0, TCSANOW, &term);
if(ch != EOF) {
ungetc(ch, stdin);
return 1;
}
return 0;
}
// 获取一个字符
int _getch() {
set_conio_terminal_mode_if_needed();
int ch;
struct termios oldt, newt;
// 获取当前终端设置
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
// 禁用缓冲和回显
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
// 读取字符
ch = getchar();
// 还原终端设置
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
#endif
#if PK_IS_DESKTOP_PLATFORM && PK_ENABLE_OS
static bool conio_kbhit(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int ret = _kbhit();
py_newint(py_retval(), ret);
return true;
}
static bool conio_getch(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int ret = _getch();
py_newint(py_retval(), ret);
return true;
}
void pk__add_module_conio() {
py_Ref mod = py_newmodule("conio");
py_bindfunc(mod, "_kbhit", conio_kbhit);
py_bindfunc(mod, "_getch", conio_getch);
}
#else
void pk__add_module_conio() {}
#endif
// src/modules\dis.c
#include <stdbool.h>
static bool disassemble(CodeObject* co) {
c11_vector /*T=int*/ jumpTargets;
c11_vector__ctor(&jumpTargets, sizeof(int));
for(int i = 0; i < co->codes.length; i++) {
Bytecode* bc = c11__at(Bytecode, &co->codes, i);
if(Bytecode__is_forward_jump(bc)) {
int target = (int16_t)bc->arg + i;
c11_vector__push(int, &jumpTargets, target);
}
}
c11_sbuf ss;
c11_sbuf__ctor(&ss);
int prev_line = -1;
for(int i = 0; i < co->codes.length; i++) {
Bytecode byte = c11__getitem(Bytecode, &co->codes, i);
BytecodeEx ex = c11__getitem(BytecodeEx, &co->codes_ex, i);
char line[8] = "";
if(ex.lineno == prev_line) {
// do nothing
} else {
snprintf(line, sizeof(line), "%d", ex.lineno);
if(prev_line != -1) c11_sbuf__write_char(&ss, '\n');
prev_line = ex.lineno;
}
char pointer[4] = "";
c11__foreach(int, &jumpTargets, it) {
if(*it == i) {
snprintf(pointer, sizeof(pointer), "->");
break;
}
}
char buf[32];
snprintf(buf, sizeof(buf), "%-8s%-3s%-3d ", line, pointer, i);
c11_sbuf__write_cstr(&ss, buf);
c11_sbuf__write_cstr(&ss, pk_opname(byte.op));
c11_sbuf__write_char(&ss, ' ');
int padding = 24 - strlen(pk_opname(byte.op));
for(int j = 0; j < padding; j++)
c11_sbuf__write_char(&ss, ' ');
do {
if(Bytecode__is_forward_jump(&byte)) {
pk_sprintf(&ss, "%d (to %d)", (int16_t)byte.arg, (int16_t)byte.arg + i);
break;
}
c11_sbuf__write_int(&ss, byte.arg);
switch(byte.op) {
case OP_LOAD_CONST: {
py_Ref value = c11__at(py_TValue, &co->consts, byte.arg);
if(py_repr(value)) {
pk_sprintf(&ss, " (%v)", py_tosv(py_retval()));
} else {
return false;
}
break;
}
case OP_FORMAT_STRING:
case OP_IMPORT_PATH: {
py_Ref path = c11__at(py_TValue, &co->consts, byte.arg);
pk_sprintf(&ss, " (%q)", py_tosv(path));
break;
}
case OP_LOAD_NAME: case OP_LOAD_NAME_AS_INT:
case OP_LOAD_GLOBAL:
case OP_LOAD_NONLOCAL:
case OP_STORE_GLOBAL:
case OP_LOAD_ATTR:
case OP_LOAD_METHOD:
case OP_STORE_ATTR:
case OP_DELETE_ATTR:
case OP_BEGIN_CLASS:
case OP_DELETE_GLOBAL:
case OP_STORE_CLASS_ATTR: {
py_Name name = c11__getitem(py_Name, &co->names, byte.arg);
pk_sprintf(&ss, " (%n)", name);
break;
}
case OP_LOAD_FAST:
case OP_STORE_FAST:
case OP_DELETE_FAST: {
py_Name name = c11__getitem(py_Name, &co->varnames, byte.arg);
pk_sprintf(&ss, " (%n)", name);
break;
}
case OP_LOAD_FUNCTION: {
const FuncDecl* decl = c11__getitem(FuncDecl*, &co->func_decls, byte.arg);
pk_sprintf(&ss, " (%s)", decl->code.name->data);
break;
}
#define CASE_BINARY_OP(label, op, rop) \
case label: { \
pk_sprintf(&ss, " (%s)", pk_op2str(op)); \
break; \
}
CASE_BINARY_OP(OP_BINARY_ADD, __add__, __radd__)
CASE_BINARY_OP(OP_BINARY_SUB, __sub__, __rsub__)
CASE_BINARY_OP(OP_BINARY_MUL, __mul__, __rmul__)
CASE_BINARY_OP(OP_BINARY_TRUEDIV, __truediv__, __rtruediv__)
CASE_BINARY_OP(OP_BINARY_FLOORDIV, __floordiv__, __rfloordiv__)
CASE_BINARY_OP(OP_BINARY_MOD, __mod__, __rmod__)
CASE_BINARY_OP(OP_BINARY_POW, __pow__, __rpow__)
CASE_BINARY_OP(OP_BINARY_LSHIFT, __lshift__, 0)
CASE_BINARY_OP(OP_BINARY_RSHIFT, __rshift__, 0)
CASE_BINARY_OP(OP_BINARY_AND, __and__, 0)
CASE_BINARY_OP(OP_BINARY_OR, __or__, 0)
CASE_BINARY_OP(OP_BINARY_XOR, __xor__, 0)
CASE_BINARY_OP(OP_BINARY_MATMUL, __matmul__, 0)
CASE_BINARY_OP(OP_COMPARE_LT, __lt__, __gt__)
CASE_BINARY_OP(OP_COMPARE_LE, __le__, __ge__)
CASE_BINARY_OP(OP_COMPARE_EQ, __eq__, __eq__)
CASE_BINARY_OP(OP_COMPARE_NE, __ne__, __ne__)
CASE_BINARY_OP(OP_COMPARE_GT, __gt__, __lt__)
CASE_BINARY_OP(OP_COMPARE_GE, __ge__, __le__)
#undef CASE_BINARY_OP
}
} while(0);
if(i != co->codes.length - 1) c11_sbuf__write_char(&ss, '\n');
}
c11_string* output = c11_sbuf__submit(&ss);
pk_current_vm->callbacks.print(output->data);
pk_current_vm->callbacks.print("\n");
c11_string__delete(output);
c11_vector__dtor(&jumpTargets);
return true;
}
static bool dis_dis(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
CodeObject* code = NULL;
if(py_istype(argv, tp_function)) {
Function* ud = py_touserdata(argv);
code = &ud->decl->code;
} else if(py_istype(argv, tp_code)) {
code = py_touserdata(argv);
} else {
return TypeError("dis() expected a code object");
}
if(!disassemble(code)) return false;
py_newnone(py_retval());
return true;
}
void pk__add_module_dis() {
py_Ref mod = py_newmodule("dis");
py_bindfunc(mod, "dis", dis_dis);
}
// src/modules\easing.c
// https://easings.net/
const double kPi = DMATH_PI;
static double easeLinear(double x) { return x; }
static double easeInSine(double x) { return 1.0 - dmath_cos(x * kPi / 2); }
static double easeOutSine(double x) { return dmath_sin(x * kPi / 2); }
static double easeInOutSine(double x) { return -(dmath_cos(kPi * x) - 1) / 2; }
static double easeInQuad(double x) { return x * x; }
static double easeOutQuad(double x) { return 1 - dmath_pow(1 - x, 2); }
static double easeInOutQuad(double x) {
if(x < 0.5) {
return 2 * x * x;
} else {
return 1 - dmath_pow(-2 * x + 2, 2) / 2;
}
}
static double easeInCubic(double x) { return x * x * x; }
static double easeOutCubic(double x) { return 1 - dmath_pow(1 - x, 3); }
static double easeInOutCubic(double x) {
if(x < 0.5) {
return 4 * x * x * x;
} else {
return 1 - dmath_pow(-2 * x + 2, 3) / 2;
}
}
static double easeInQuart(double x) { return dmath_pow(x, 4); }
static double easeOutQuart(double x) { return 1 - dmath_pow(1 - x, 4); }
static double easeInOutQuart(double x) {
if(x < 0.5) {
return 8 * dmath_pow(x, 4);
} else {
return 1 - dmath_pow(-2 * x + 2, 4) / 2;
}
}
static double easeInQuint(double x) { return dmath_pow(x, 5); }
static double easeOutQuint(double x) { return 1 - dmath_pow(1 - x, 5); }
static double easeInOutQuint(double x) {
if(x < 0.5) {
return 16 * dmath_pow(x, 5);
} else {
return 1 - dmath_pow(-2 * x + 2, 5) / 2;
}
}
static double easeInExpo(double x) { return x == 0 ? 0 : dmath_pow(2, 10 * x - 10); }
static double easeOutExpo(double x) { return x == 1 ? 1 : 1 - dmath_pow(2, -10 * x); }
static double easeInOutExpo(double x) {
if(x == 0) {
return 0;
} else if(x == 1) {
return 1;
} else if(x < 0.5) {
return dmath_pow(2, 20 * x - 10) / 2;
} else {
return (2 - dmath_pow(2, -20 * x + 10)) / 2;
}
}
static double easeInCirc(double x) { return 1 - dmath_sqrt(1 - dmath_pow(x, 2)); }
static double easeOutCirc(double x) { return dmath_sqrt(1 - dmath_pow(x - 1, 2)); }
static double easeInOutCirc(double x) {
if(x < 0.5) {
return (1 - dmath_sqrt(1 - dmath_pow(2 * x, 2))) / 2;
} else {
return (dmath_sqrt(1 - dmath_pow(-2 * x + 2, 2)) + 1) / 2;
}
}
static double easeInBack(double x) {
const double c1 = 1.70158;
const double c3 = c1 + 1;
return c3 * x * x * x - c1 * x * x;
}
static double easeOutBack(double x) {
const double c1 = 1.70158;
const double c3 = c1 + 1;
return 1 + c3 * dmath_pow(x - 1, 3) + c1 * dmath_pow(x - 1, 2);
}
static double easeInOutBack(double x) {
const double c1 = 1.70158;
const double c2 = c1 * 1.525;
if(x < 0.5) {
return (dmath_pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2;
} else {
return (dmath_pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
}
}
static double easeInElastic(double x) {
const double c4 = (2 * kPi) / 3;
if(x == 0) {
return 0;
} else if(x == 1) {
return 1;
} else {
return -dmath_pow(2, 10 * x - 10) * dmath_sin((x * 10 - 10.75) * c4);
}
}
static double easeOutElastic(double x) {
const double c4 = (2 * kPi) / 3;
if(x == 0) {
return 0;
} else if(x == 1) {
return 1;
} else {
return dmath_pow(2, -10 * x) * dmath_sin((x * 10 - 0.75) * c4) + 1;
}
}
static double easeInOutElastic(double x) {
const double c5 = (2 * kPi) / 4.5;
if(x == 0) {
return 0;
} else if(x == 1) {
return 1;
} else if(x < 0.5) {
return -(dmath_pow(2, 20 * x - 10) * dmath_sin((20 * x - 11.125) * c5)) / 2;
} else {
return (dmath_pow(2, -20 * x + 10) * dmath_sin((20 * x - 11.125) * c5)) / 2 + 1;
}
}
static double easeOutBounce(double x) {
const double n1 = 7.5625;
const double d1 = 2.75;
if(x < 1 / d1) {
return n1 * x * x;
} else if(x < 2 / d1) {
x -= 1.5 / d1;
return n1 * x * x + 0.75;
} else if(x < 2.5 / d1) {
x -= 2.25 / d1;
return n1 * x * x + 0.9375;
} else {
x -= 2.625 / d1;
return n1 * x * x + 0.984375;
}
}
static double easeInBounce(double x) { return 1 - easeOutBounce(1 - x); }
static double easeInOutBounce(double x) {
return x < 0.5 ? (1 - easeOutBounce(1 - 2 * x)) / 2 : (1 + easeOutBounce(2 * x - 1)) / 2;
}
#define DEF_EASE(name) \
static bool easing_##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
py_f64 t; \
if(!py_castfloat(argv, &t)) return false; \
py_newfloat(py_retval(), ease##name(t)); \
return true; \
}
DEF_EASE(Linear)
DEF_EASE(InSine)
DEF_EASE(OutSine)
DEF_EASE(InOutSine)
DEF_EASE(InQuad)
DEF_EASE(OutQuad)
DEF_EASE(InOutQuad)
DEF_EASE(InCubic)
DEF_EASE(OutCubic)
DEF_EASE(InOutCubic)
DEF_EASE(InQuart)
DEF_EASE(OutQuart)
DEF_EASE(InOutQuart)
DEF_EASE(InQuint)
DEF_EASE(OutQuint)
DEF_EASE(InOutQuint)
DEF_EASE(InExpo)
DEF_EASE(OutExpo)
DEF_EASE(InOutExpo)
DEF_EASE(InCirc)
DEF_EASE(OutCirc)
DEF_EASE(InOutCirc)
DEF_EASE(InBack)
DEF_EASE(OutBack)
DEF_EASE(InOutBack)
DEF_EASE(InElastic)
DEF_EASE(OutElastic)
DEF_EASE(InOutElastic)
DEF_EASE(InBounce)
DEF_EASE(OutBounce)
DEF_EASE(InOutBounce)
#undef DEF_EASE
void pk__add_module_easing() {
py_GlobalRef mod = py_newmodule("easing");
py_bindfunc(mod, "Linear", easing_Linear);
py_bindfunc(mod, "InSine", easing_InSine);
py_bindfunc(mod, "OutSine", easing_OutSine);
py_bindfunc(mod, "InOutSine", easing_InOutSine);
py_bindfunc(mod, "InQuad", easing_InQuad);
py_bindfunc(mod, "OutQuad", easing_OutQuad);
py_bindfunc(mod, "InOutQuad", easing_InOutQuad);
py_bindfunc(mod, "InCubic", easing_InCubic);
py_bindfunc(mod, "OutCubic", easing_OutCubic);
py_bindfunc(mod, "InOutCubic", easing_InOutCubic);
py_bindfunc(mod, "InQuart", easing_InQuart);
py_bindfunc(mod, "OutQuart", easing_OutQuart);
py_bindfunc(mod, "InOutQuart", easing_InOutQuart);
py_bindfunc(mod, "InQuint", easing_InQuint);
py_bindfunc(mod, "OutQuint", easing_OutQuint);
py_bindfunc(mod, "InOutQuint", easing_InOutQuint);
py_bindfunc(mod, "InExpo", easing_InExpo);
py_bindfunc(mod, "OutExpo", easing_OutExpo);
py_bindfunc(mod, "InOutExpo", easing_InOutExpo);
py_bindfunc(mod, "InCirc", easing_InCirc);
py_bindfunc(mod, "OutCirc", easing_OutCirc);
py_bindfunc(mod, "InOutCirc", easing_InOutCirc);
py_bindfunc(mod, "InBack", easing_InBack);
py_bindfunc(mod, "OutBack", easing_OutBack);
py_bindfunc(mod, "InOutBack", easing_InOutBack);
py_bindfunc(mod, "InElastic", easing_InElastic);
py_bindfunc(mod, "OutElastic", easing_OutElastic);
py_bindfunc(mod, "InOutElastic", easing_InOutElastic);
py_bindfunc(mod, "InBounce", easing_InBounce);
py_bindfunc(mod, "OutBounce", easing_OutBounce);
py_bindfunc(mod, "InOutBounce", easing_InOutBounce);
}
// src/modules\enum.c
static bool Enum__wrapper_field(py_Name name, py_Ref value, void* ctx) {
c11_sv name_sv = py_name2sv(name);
if(name_sv.size == 0 || name_sv.data[0] == '_') return true;
py_push(ctx);
py_pushnil();
py_assign(py_pushtmp(), py_name2ref(name));
py_push(value);
bool ok = py_vectorcall(2, 0);
if(!ok) return false;
py_assign(value, py_retval());
return true;
}
static void Enum__on_end_subclass(py_TypeInfo* derived_ti) {
derived_ti->is_final = true;
py_applydict(&derived_ti->self, Enum__wrapper_field, &derived_ti->self);
}
static bool Enum__new__(int argc, py_Ref argv) {
py_newobject(py_retval(), py_totype(argv), 2, 0);
return true;
}
static bool Enum__init__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
py_setslot(argv, 0, py_arg(1));
py_setslot(argv, 1, py_arg(2));
py_newnone(py_retval());
return true;
}
static bool Enum__str__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
// f'{type(self).__name__}.{self.name}'
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, py_tpname(argv->type));
c11_sbuf__write_char(&buf, '.');
c11_sbuf__write_cstr(&buf, py_tostr(py_getslot(argv, 0)));
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool Enum__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
// f'<{str(self)}: {self.value!r}>'
if(!py_str(argv)) return false;
py_push(py_retval()); // str(self)
if(!py_repr(py_getslot(argv, 1))) return false;
py_push(py_retval()); // repr(self.value)
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, "<");
c11_sbuf__write_cstr(&buf, py_tostr(py_peek(-2)));
c11_sbuf__write_cstr(&buf, ": ");
c11_sbuf__write_cstr(&buf, py_tostr(py_peek(-1)));
c11_sbuf__write_cstr(&buf, ">");
c11_sbuf__py_submit(&buf, py_retval());
py_shrink(2);
return true;
}
static bool Enum__name(int argc, py_Ref argv) {
py_assign(py_retval(), py_getslot(argv, 0));
return true;
}
static bool Enum__value(int argc, py_Ref argv) {
py_assign(py_retval(), py_getslot(argv, 1));
return true;
}
void pk__add_module_enum() {
py_Ref mod = py_newmodule("enum");
py_Type type = py_newtype("Enum", tp_object, mod, NULL);
py_bindmagic(type, __new__, Enum__new__);
py_bindmagic(type, __init__, Enum__init__);
py_bindmagic(type, __str__, Enum__str__);
py_bindmagic(type, __repr__, Enum__repr__);
py_bindproperty(type, "name", Enum__name, NULL);
py_bindproperty(type, "value", Enum__value, NULL);
pk_typeinfo(type)->on_end_subclass = Enum__on_end_subclass;
}
// src/modules\gc.c
static bool gc_enable(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
heap->gc_enabled = true;
py_newnone(py_retval());
return true;
}
static bool gc_disable(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
heap->gc_enabled = false;
py_newnone(py_retval());
return true;
}
static bool gc_isenabled(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
py_newbool(py_retval(), heap->gc_enabled);
return true;
}
static bool gc_collect(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
int freed = ManagedHeap__collect(heap);
py_newint(py_retval(), freed);
return true;
}
static bool gc_collect_hint(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
int freed = ManagedHeap__collect_hint(heap);
py_newint(py_retval(), freed);
return true;
}
static bool gc_setup_debug_callback(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
ManagedHeap* heap = &pk_current_vm->heap;
heap->debug_callback = *argv;
py_newnone(py_retval());
return true;
}
void pk__add_module_gc() {
py_Ref mod = py_newmodule("gc");
py_bindfunc(mod, "enable", gc_enable);
py_bindfunc(mod, "disable", gc_disable);
py_bindfunc(mod, "isenabled", gc_isenabled);
py_bindfunc(mod, "collect", gc_collect);
py_bindfunc(mod, "collect_hint", gc_collect_hint);
py_bindfunc(mod, "setup_debug_callback", gc_setup_debug_callback);
}
// src/modules\importlib.c
static bool importlib_reload(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_module);
return py_importlib_reload(argv);
}
void pk__add_module_importlib() {
py_Ref mod = py_newmodule("importlib");
py_bindfunc(mod, "reload", importlib_reload);
}
// src/modules\inspect.c
static bool inspect_isgeneratorfunction(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref obj = argv;
if(py_istype(argv, tp_boundmethod)) {
py_TValue* slots = PyObject__slots(argv->_obj);
obj = &slots[1]; // callable
}
if(py_istype(obj, tp_function)) {
Function* fn = py_touserdata(obj);
py_newbool(py_retval(), fn->decl->type == FuncType_GENERATOR);
} else {
py_newbool(py_retval(), false);
}
return true;
}
static bool inspect_is_user_defined_type(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_type);
py_TypeInfo* ti = py_touserdata(argv);
py_newbool(py_retval(), ti->is_python);
return true;
}
void pk__add_module_inspect() {
py_Ref mod = py_newmodule("inspect");
py_bindfunc(mod, "isgeneratorfunction", inspect_isgeneratorfunction);
py_bindfunc(mod, "is_user_defined_type", inspect_is_user_defined_type);
}
// src/modules\json.c
static bool json_loads(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* source = py_tostr(argv);
return py_json_loads(source);
}
static bool json_dumps(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_int);
int indent = py_toint(&argv[1]);
return py_json_dumps(argv, indent);
}
void pk__add_module_json() {
py_Ref mod = py_newmodule("json");
py_setdict(mod, py_name("null"), py_None());
py_setdict(mod, py_name("true"), py_True());
py_setdict(mod, py_name("false"), py_False());
py_TValue tmp;
py_newfloat(&tmp, DMATH_NAN);
py_setdict(mod, py_name("NaN"), &tmp);
py_newfloat(&tmp, DMATH_INFINITY);
py_setdict(mod, py_name("Infinity"), &tmp);
py_bindfunc(mod, "loads", json_loads);
py_bind(mod, "dumps(obj, indent=0)", json_dumps);
}
typedef struct {
c11_sbuf* buf;
bool first;
int indent;
int depth;
} json__write_dict_kv_ctx;
static bool json__write_object(c11_sbuf* buf, py_TValue* obj, int indent, int depth);
static void json__write_indent(c11_sbuf* buf, int n_spaces) {
for(int i = 0; i < n_spaces; i++) {
c11_sbuf__write_char(buf, ' ');
}
}
static bool json__write_array(c11_sbuf* buf, py_TValue* arr, int length, int indent, int depth) {
c11_sbuf__write_char(buf, '[');
if(length == 0) {
c11_sbuf__write_char(buf, ']');
return true;
}
if(indent > 0) c11_sbuf__write_char(buf, '\n');
int n_spaces = indent * depth;
const char* sep = indent > 0 ? ",\n" : ", ";
for(int i = 0; i < length; i++) {
if(i != 0) c11_sbuf__write_cstr(buf, sep);
json__write_indent(buf, n_spaces);
bool ok = json__write_object(buf, arr + i, indent, depth);
if(!ok) return false;
}
if(indent > 0) {
c11_sbuf__write_char(buf, '\n');
json__write_indent(buf, n_spaces - indent);
}
c11_sbuf__write_char(buf, ']');
return true;
}
static bool json__write_dict_kv(py_Ref k, py_Ref v, void* ctx_) {
json__write_dict_kv_ctx* ctx = ctx_;
int n_spaces = ctx->indent * ctx->depth;
const char* sep = ctx->indent > 0 ? ",\n" : ", ";
if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, sep);
ctx->first = false;
if(!py_isstr(k)) return TypeError("keys must be strings");
json__write_indent(ctx->buf, n_spaces);
c11_sbuf__write_quoted(ctx->buf, py_tosv(k), '"');
c11_sbuf__write_cstr(ctx->buf, ": ");
return json__write_object(ctx->buf, v, ctx->indent, ctx->depth);
}
static bool json__write_namedict_kv(py_Name k, py_Ref v, void* ctx_) {
json__write_dict_kv_ctx* ctx = ctx_;
int n_spaces = ctx->indent * ctx->depth;
const char* sep = ctx->indent > 0 ? ",\n" : ", ";
if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, sep);
ctx->first = false;
json__write_indent(ctx->buf, n_spaces);
c11_sbuf__write_quoted(ctx->buf, py_name2sv(k), '"');
c11_sbuf__write_cstr(ctx->buf, ": ");
return json__write_object(ctx->buf, v, ctx->indent, ctx->depth);
}
static bool json__write_object(c11_sbuf* buf, py_TValue* obj, int indent, int depth) {
switch(obj->type) {
case tp_NoneType: c11_sbuf__write_cstr(buf, "null"); return true;
case tp_int: c11_sbuf__write_int(buf, obj->_i64); return true;
case tp_float: {
if(dmath_isnan(obj->_f64)) {
c11_sbuf__write_cstr(buf, "NaN");
} else if(dmath_isinf(obj->_f64)) {
c11_sbuf__write_cstr(buf, obj->_f64 < 0 ? "-Infinity" : "Infinity");
} else {
c11_sbuf__write_f64(buf, obj->_f64, -1);
}
return true;
}
case tp_bool: {
c11_sbuf__write_cstr(buf, py_tobool(obj) ? "true" : "false");
return true;
}
case tp_str: {
c11_sbuf__write_quoted(buf, py_tosv(obj), '"');
return true;
}
case tp_list: {
return json__write_array(buf, py_list_data(obj), py_list_len(obj), indent, depth + 1);
}
case tp_tuple: {
return json__write_array(buf, py_tuple_data(obj), py_tuple_len(obj), indent, depth + 1);
}
case tp_dict: {
c11_sbuf__write_char(buf, '{');
if(py_dict_len(obj) == 0) {
c11_sbuf__write_char(buf, '}');
return true;
}
if(indent > 0) c11_sbuf__write_char(buf, '\n');
json__write_dict_kv_ctx ctx = {.buf = buf,
.first = true,
.indent = indent,
.depth = depth + 1};
bool ok = py_dict_apply(obj, json__write_dict_kv, &ctx);
if(!ok) return false;
if(indent > 0) {
c11_sbuf__write_char(buf, '\n');
json__write_indent(buf, indent * depth);
}
c11_sbuf__write_char(buf, '}');
return true;
}
case tp_namedict: {
py_Ref original = py_getslot(obj, 0);
c11_sbuf__write_char(buf, '{');
if(PyObject__dict(original->_obj)->length == 0) {
c11_sbuf__write_char(buf, '}');
return true;
}
if(indent > 0) c11_sbuf__write_char(buf, '\n');
json__write_dict_kv_ctx ctx = {.buf = buf,
.first = true,
.indent = indent,
.depth = depth + 1};
bool ok = py_applydict(original, json__write_namedict_kv, &ctx);
if(!ok) return false;
if(indent > 0) {
c11_sbuf__write_char(buf, '\n');
json__write_indent(buf, indent * depth);
}
c11_sbuf__write_char(buf, '}');
return true;
}
default: return TypeError("'%t' object is not JSON serializable", obj->type);
}
}
bool py_json_dumps(py_Ref val, int indent) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
bool ok = json__write_object(&buf, val, indent, 0);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
bool py_json_loads(const char* source) {
py_GlobalRef mod = py_getmodule("json");
return py_exec(source, "<json>", EVAL_MODE, mod);
}
// src/modules\lz4.c
#ifdef PK_BUILD_MODULE_LZ4
#include <string.h>
#include <assert.h>
#include "lz4/lib/lz4.h"
static bool lz4_compress(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_bytes);
int src_size;
const void* src = py_tobytes(argv, &src_size);
int dst_capacity = LZ4_compressBound(src_size);
char* p = (char*)py_newbytes(py_retval(), sizeof(int) + dst_capacity);
memcpy(p, &src_size, sizeof(int));
char* dst = p + sizeof(int);
int dst_size = LZ4_compress_default(src, dst, src_size, dst_capacity);
if(dst_size <= 0) return ValueError("LZ4 compression failed");
py_bytes_resize(py_retval(), sizeof(int) + dst_size);
return true;
}
static bool lz4_decompress(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_bytes);
int total_size;
const int* p = (int*)py_tobytes(argv, &total_size);
const char* src = (const char*)(p + 1);
if(total_size < sizeof(int)) return ValueError("invalid LZ4 data");
int uncompressed_size = *p;
if(uncompressed_size < 0) return ValueError("invalid LZ4 data");
char* dst = (char*)py_newbytes(py_retval(), uncompressed_size);
int dst_size = LZ4_decompress_safe(src, dst, total_size - sizeof(int), uncompressed_size);
if(dst_size < 0) return ValueError("LZ4 decompression failed");
assert(dst_size == uncompressed_size);
return true;
}
void pk__add_module_lz4() {
py_Ref mod = py_newmodule("lz4");
py_bindfunc(mod, "compress", lz4_compress);
py_bindfunc(mod, "decompress", lz4_decompress);
}
#else
void pk__add_module_lz4() {}
#endif
// src/modules\math.c
#define ONE_ARG_FUNC(name, func) \
static bool math_##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
double x; \
if(!py_castfloat(py_arg(0), &x)) return false; \
py_newfloat(py_retval(), func(x)); \
return true; \
}
#define ONE_ARG_BOOL_FUNC(name, func) \
static bool math_##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
double x; \
if(!py_castfloat(py_arg(0), &x)) return false; \
py_newbool(py_retval(), func(x)); \
return true; \
}
#define TWO_ARG_FUNC(name, func) \
static bool math_##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
double x, y; \
if(!py_castfloat(py_arg(0), &x)) return false; \
if(!py_castfloat(py_arg(1), &y)) return false; \
py_newfloat(py_retval(), func(x, y)); \
return true; \
}
ONE_ARG_FUNC(ceil, dmath_ceil)
ONE_ARG_FUNC(fabs, dmath_fabs)
ONE_ARG_FUNC(floor, dmath_floor)
ONE_ARG_FUNC(trunc, dmath_trunc)
static bool math_fsum(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_list);
py_Ref list = py_arg(0);
double sum = 0;
double c = 0;
for(int i = 0; i < py_list_len(list); i++) {
py_Ref item = py_list_getitem(list, i);
double x;
if(!py_castfloat(item, &x)) return false;
double y = x - c;
double t = sum + y;
c = (t - sum) - y;
sum = t;
}
py_newfloat(py_retval(), sum);
return true;
}
static bool math_gcd(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
py_i64 a = py_toint(py_arg(0));
py_i64 b = py_toint(py_arg(1));
if(a < 0) a = -a;
if(b < 0) b = -b;
while(b != 0) {
py_i64 t = b;
b = a % b;
a = t;
}
py_newint(py_retval(), a);
return true;
}
ONE_ARG_BOOL_FUNC(isfinite, dmath_isfinite)
ONE_ARG_BOOL_FUNC(isinf, dmath_isinf)
ONE_ARG_BOOL_FUNC(isnan, dmath_isnan)
static bool math_isclose(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
double a, b;
if(!py_castfloat(py_arg(0), &a)) return false;
if(!py_castfloat(py_arg(1), &b)) return false;
py_newbool(py_retval(), dmath_fabs(a - b) < 1e-9);
return true;
}
ONE_ARG_FUNC(exp, dmath_exp)
static bool math_log(int argc, py_Ref argv) {
double x;
if(!py_castfloat(py_arg(0), &x)) return false;
if(argc == 1) {
py_newfloat(py_retval(), dmath_log(x));
} else if(argc == 2) {
double base;
if(!py_castfloat(py_arg(1), &base)) return false;
py_newfloat(py_retval(), dmath_log2(x) / dmath_log2(base));
} else {
return TypeError("log() takes 1 or 2 arguments");
}
return true;
}
ONE_ARG_FUNC(log2, dmath_log2)
ONE_ARG_FUNC(log10, dmath_log10)
TWO_ARG_FUNC(pow, dmath_pow)
ONE_ARG_FUNC(sqrt, dmath_sqrt)
ONE_ARG_FUNC(acos, dmath_acos)
ONE_ARG_FUNC(asin, dmath_asin)
ONE_ARG_FUNC(atan, dmath_atan)
ONE_ARG_FUNC(cos, dmath_cos)
ONE_ARG_FUNC(sin, dmath_sin)
ONE_ARG_FUNC(tan, dmath_tan)
TWO_ARG_FUNC(atan2, dmath_atan2)
static bool math_degrees(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
double x;
if(!py_castfloat(py_arg(0), &x)) return false;
py_newfloat(py_retval(), x * DMATH_RAD2DEG);
return true;
}
static bool math_radians(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
double x;
if(!py_castfloat(py_arg(0), &x)) return false;
py_newfloat(py_retval(), x * DMATH_DEG2RAD);
return true;
}
TWO_ARG_FUNC(fmod, dmath_fmod)
TWO_ARG_FUNC(copysign, dmath_copysign)
static bool math_modf(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
double i;
double f = dmath_modf(py_tofloat(py_arg(0)), &i);
py_Ref p = py_newtuple(py_retval(), 2);
py_newfloat(&p[0], f);
py_newfloat(&p[1], i);
return true;
}
static bool math_factorial(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
py_i64 n = py_toint(py_arg(0));
if(n < 0) return ValueError("factorial() not defined for negative values");
py_i64 r = 1;
for(py_i64 i = 2; i <= n; i++)
r *= i;
py_newint(py_retval(), r);
return true;
}
void pk__add_module_math() {
py_Ref mod = py_newmodule("math");
py_newfloat(py_emplacedict(mod, py_name("pi")), DMATH_PI);
py_newfloat(py_emplacedict(mod, py_name("e")), DMATH_E);
py_newfloat(py_emplacedict(mod, py_name("inf")), DMATH_INFINITY);
py_newfloat(py_emplacedict(mod, py_name("nan")), DMATH_NAN);
py_bindfunc(mod, "ceil", math_ceil);
py_bindfunc(mod, "fabs", math_fabs);
py_bindfunc(mod, "floor", math_floor);
py_bindfunc(mod, "trunc", math_trunc);
py_bindfunc(mod, "fsum", math_fsum);
py_bindfunc(mod, "gcd", math_gcd);
py_bindfunc(mod, "isfinite", math_isfinite);
py_bindfunc(mod, "isinf", math_isinf);
py_bindfunc(mod, "isnan", math_isnan);
py_bindfunc(mod, "isclose", math_isclose);
py_bindfunc(mod, "exp", math_exp);
py_bindfunc(mod, "log", math_log);
py_bindfunc(mod, "log2", math_log2);
py_bindfunc(mod, "log10", math_log10);
py_bindfunc(mod, "pow", math_pow);
py_bindfunc(mod, "sqrt", math_sqrt);
py_bindfunc(mod, "acos", math_acos);
py_bindfunc(mod, "asin", math_asin);
py_bindfunc(mod, "atan", math_atan);
py_bindfunc(mod, "cos", math_cos);
py_bindfunc(mod, "sin", math_sin);
py_bindfunc(mod, "tan", math_tan);
py_bindfunc(mod, "atan2", math_atan2);
py_bindfunc(mod, "degrees", math_degrees);
py_bindfunc(mod, "radians", math_radians);
py_bindfunc(mod, "fmod", math_fmod);
py_bindfunc(mod, "modf", math_modf);
py_bindfunc(mod, "copysign", math_copysign);
py_bindfunc(mod, "factorial", math_factorial);
}
#undef ONE_ARG_FUNC
#undef ONE_ARG_BOOL_FUNC
#undef TWO_ARG_FUNC
// src/modules\os.c
#if PK_ENABLE_OS
#include <errno.h>
#if PY_SYS_PLATFORM == 0
#include <direct.h>
#include <io.h>
int platform_chdir(const char* path) { return _chdir(path); }
bool platform_getcwd(char* buf, size_t size) { return _getcwd(buf, size) != NULL; }
bool platform_path_exists(const char* path) { return _access(path, 0) == 0; }
#elif PY_SYS_PLATFORM == 3 || PY_SYS_PLATFORM == 5
#include <unistd.h>
int platform_chdir(const char* path) { return chdir(path); }
bool platform_getcwd(char* buf, size_t size) { return getcwd(buf, size) != NULL; }
bool platform_path_exists(const char* path) { return access(path, F_OK) == 0; }
#else
int platform_chdir(const char* path) { return -1; }
bool platform_getcwd(char* buf, size_t size) { return false; }
bool platform_path_exists(const char* path) { return false; }
#endif
static bool os_chdir(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0));
int code = platform_chdir(path);
if(code != 0) {
const char* msg = strerror(errno);
return OSError("[Errno %d] %s: '%s'", errno, msg, path);
}
py_newnone(py_retval());
return true;
}
static bool os_getcwd(int argc, py_Ref argv) {
char buf[1024];
if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
py_newstr(py_retval(), buf);
return true;
}
static bool os_system(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
#if PK_IS_DESKTOP_PLATFORM
const char* cmd = py_tostr(py_arg(0));
int code = system(cmd);
py_newint(py_retval(), code);
return true;
#else
return OSError("system() is not supported on this platform");
#endif
}
static bool os_remove(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0));
int code = remove(path);
if(code != 0) {
const char* msg = strerror(errno);
return OSError("[Errno %d] %s: '%s'", errno, msg, path);
}
py_newnone(py_retval());
return true;
}
static bool os_path_exists(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0));
py_newbool(py_retval(), platform_path_exists(path));
return true;
}
void pk__add_module_os() {
py_Ref mod = py_newmodule("os");
py_bindfunc(mod, "chdir", os_chdir);
py_bindfunc(mod, "getcwd", os_getcwd);
py_bindfunc(mod, "system", os_system);
py_bindfunc(mod, "remove", os_remove);
py_ItemRef path_object = py_emplacedict(mod, py_name("path"));
py_newobject(path_object, tp_object, -1, 0);
py_bindfunc(path_object, "exists", os_path_exists);
py_newdict(py_emplacedict(mod, py_name("environ")));
}
static bool io_FileIO__new__(int argc, py_Ref argv) {
// __new__(cls, file, mode)
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_str);
py_Type cls = py_totype(argv);
io_FileIO* ud = py_newobject(py_retval(), cls, 0, sizeof(io_FileIO));
ud->path = py_tostr(py_arg(1));
ud->mode = py_tostr(py_arg(2));
ud->file = fopen(ud->path, ud->mode);
if(ud->file == NULL) {
const char* msg = strerror(errno);
return OSError("[Errno %d] %s: '%s'", errno, msg, ud->path);
}
return true;
}
static bool io_FileIO__enter__(int argc, py_Ref argv) {
py_assign(py_retval(), py_arg(0));
return true;
}
static bool io_FileIO__exit__(int argc, py_Ref argv) {
io_FileIO* ud = py_touserdata(py_arg(0));
if(ud->file != NULL) {
fclose(ud->file);
ud->file = NULL;
}
py_newnone(py_retval());
return true;
}
static bool io_FileIO_read(int argc, py_Ref argv) {
io_FileIO* ud = py_touserdata(py_arg(0));
bool is_binary = ud->mode[strlen(ud->mode) - 1] == 'b';
int size;
if(argc == 1) {
long current = ftell(ud->file);
fseek(ud->file, 0, SEEK_END);
size = ftell(ud->file);
fseek(ud->file, current, SEEK_SET);
} else if(argc == 2) {
PY_CHECK_ARG_TYPE(1, tp_int);
size = py_toint(py_arg(1));
} else {
return TypeError("read() takes at most 2 arguments (%d given)", argc);
}
if(is_binary) {
void* dst = py_newbytes(py_retval(), size);
int actual_size = fread(dst, 1, size, ud->file);
py_bytes_resize(py_retval(), actual_size);
} else {
void* dst = PK_MALLOC(size);
int actual_size = fread(dst, 1, size, ud->file);
py_newstrv(py_retval(), (c11_sv){dst, actual_size});
PK_FREE(dst);
}
return true;
}
static bool io_FileIO_tell(int argc, py_Ref argv) {
io_FileIO* ud = py_touserdata(py_arg(0));
py_newint(py_retval(), ftell(ud->file));
return true;
}
static bool io_FileIO_seek(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
io_FileIO* ud = py_touserdata(py_arg(0));
long cookie = py_toint(py_arg(1));
int whence = py_toint(py_arg(2));
py_newint(py_retval(), fseek(ud->file, cookie, whence));
return true;
}
static bool io_FileIO_close(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
io_FileIO* ud = py_touserdata(py_arg(0));
if(ud->file != NULL) {
fclose(ud->file);
ud->file = NULL;
}
py_newnone(py_retval());
return true;
}
static bool io_FileIO_write(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
io_FileIO* ud = py_touserdata(py_arg(0));
size_t written_size;
if(ud->mode[strlen(ud->mode) - 1] == 'b') {
PY_CHECK_ARG_TYPE(1, tp_bytes);
int filesize;
unsigned char* data = py_tobytes(py_arg(1), &filesize);
written_size = fwrite(data, 1, filesize, ud->file);
} else {
PY_CHECK_ARG_TYPE(1, tp_str);
c11_sv sv = py_tosv(py_arg(1));
written_size = fwrite(sv.data, 1, sv.size, ud->file);
}
py_newint(py_retval(), written_size);
return true;
}
static bool io_FileIO_flush(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
io_FileIO* ud = py_touserdata(py_arg(0));
fflush(ud->file);
py_newnone(py_retval());
return true;
}
void pk__add_module_io() {
py_Ref mod = py_newmodule("io");
py_Type FileIO = pk_newtype("FileIO", tp_object, mod, NULL, false, true);
py_bindmagic(FileIO, __new__, io_FileIO__new__);
py_bindmagic(FileIO, __enter__, io_FileIO__enter__);
py_bindmagic(FileIO, __exit__, io_FileIO__exit__);
py_bindmethod(FileIO, "read", io_FileIO_read);
py_bindmethod(FileIO, "write", io_FileIO_write);
py_bindmethod(FileIO, "close", io_FileIO_close);
py_bindmethod(FileIO, "tell", io_FileIO_tell);
py_bindmethod(FileIO, "seek", io_FileIO_seek);
py_bindmethod(FileIO, "flush", io_FileIO_flush);
py_newint(py_emplacedict(mod, py_name("SEEK_SET")), SEEK_SET);
py_newint(py_emplacedict(mod, py_name("SEEK_CUR")), SEEK_CUR);
py_newint(py_emplacedict(mod, py_name("SEEK_END")), SEEK_END);
py_setdict(pk_current_vm->builtins, py_name("open"), py_tpobject(FileIO));
}
#else
void pk__add_module_os() {}
void pk__add_module_io() {}
#endif
static bool sys_setrecursionlimit(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
int limit = py_toint(py_arg(0));
if(limit <= pk_current_vm->recursion_depth) return ValueError("the limit is too low");
pk_current_vm->max_recursion_depth = limit;
py_newnone(py_retval());
return true;
}
static bool sys_getrecursionlimit(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_newint(py_retval(), pk_current_vm->max_recursion_depth);
return true;
}
void pk__add_module_sys() {
py_Ref mod = py_newmodule("sys");
py_newstr(py_emplacedict(mod, py_name("platform")), PY_SYS_PLATFORM_STRING);
py_newstr(py_emplacedict(mod, py_name("version")), PK_VERSION);
py_newlist(py_emplacedict(mod, py_name("argv")));
py_bindfunc(mod, "setrecursionlimit", sys_setrecursionlimit);
py_bindfunc(mod, "getrecursionlimit", sys_getrecursionlimit);
}
// src/modules\pickle.c
#include <stdint.h>
typedef enum {
// clang-format off
PKL_MEMO_GET,
PKL_MEMO_SET,
PKL_NIL, PKL_NONE, PKL_ELLIPSIS,
PKL_INT_0, PKL_INT_1, PKL_INT_2, PKL_INT_3, PKL_INT_4, PKL_INT_5, PKL_INT_6, PKL_INT_7,
PKL_INT_8, PKL_INT_9, PKL_INT_10, PKL_INT_11, PKL_INT_12, PKL_INT_13, PKL_INT_14, PKL_INT_15,
PKL_INT8, PKL_INT16, PKL_INT32, PKL_INT64,
PKL_FLOAT32, PKL_FLOAT64,
PKL_TRUE, PKL_FALSE,
PKL_STRING, PKL_BYTES,
PKL_BUILD_LIST,
PKL_BUILD_TUPLE,
PKL_BUILD_DICT,
PKL_VEC2, PKL_VEC3,
PKL_VEC2I, PKL_VEC3I,
PKL_TYPE,
PKL_ARRAY2D,
PKL_IMPORT_PATH,
PKL_GETATTR,
PKL_TVALUE,
PKL_CALL,
PKL_OBJECT,
PKL_EOF,
// clang-format on
} PickleOp;
typedef struct {
bool* used_types;
int used_types_length;
c11_smallmap_p2i memo;
c11_vector /*T=char*/ codes;
} PickleObject;
static void PickleObject__ctor(PickleObject* self) {
self->used_types_length = pk_current_vm->types.length;
self->used_types = PK_MALLOC(self->used_types_length);
memset(self->used_types, 0, self->used_types_length);
c11_smallmap_p2i__ctor(&self->memo);
c11_vector__ctor(&self->codes, sizeof(char));
}
static void PickleObject__dtor(PickleObject* self) {
PK_FREE(self->used_types);
c11_smallmap_p2i__dtor(&self->memo);
c11_vector__dtor(&self->codes);
}
static bool PickleObject__py_submit(PickleObject* self, py_OutRef out);
static void PickleObject__write_bytes(PickleObject* buf, const void* data, int size) {
c11_vector__extend(&buf->codes, data, size);
}
static void c11_sbuf__write_type_path(c11_sbuf* path_buf, py_Type type) {
py_TypeInfo* ti = pk_typeinfo(type);
if(py_isnil(ti->module)) {
c11_sbuf__write_cstr(path_buf, py_name2str(ti->name));
return;
}
py_ModuleInfo* mi = py_touserdata(ti->module);
c11_sbuf__write_sv(path_buf, c11_string__sv(mi->path));
c11_sbuf__write_char(path_buf, '.');
c11_sbuf__write_sv(path_buf, py_name2sv(ti->name));
}
static void pkl__emit_op(PickleObject* buf, PickleOp op) {
c11_vector__push(char, &buf->codes, op);
}
static void pkl__emit_int(PickleObject* buf, py_i64 val) {
if(val >= 0 && val <= 15) {
pkl__emit_op(buf, PKL_INT_0 + val);
return;
}
if(INT8_MIN <= val && val <= INT8_MAX) {
pkl__emit_op(buf, PKL_INT8);
PickleObject__write_bytes(buf, &val, 1);
} else if(INT16_MIN <= val && val <= INT16_MAX) {
pkl__emit_op(buf, PKL_INT16);
PickleObject__write_bytes(buf, &val, 2);
} else if(INT32_MIN <= val && val <= INT32_MAX) {
pkl__emit_op(buf, PKL_INT32);
PickleObject__write_bytes(buf, &val, 4);
} else {
pkl__emit_op(buf, PKL_INT64);
PickleObject__write_bytes(buf, &val, 8);
}
}
static void pkl__emit_cstr(PickleObject* buf, const char* s) {
PickleObject__write_bytes(buf, s, strlen(s) + 1);
}
const static char* pkl__read_cstr(const unsigned char** p) {
const char* s = (const char*)*p;
(*p) += strlen(s) + 1;
return s;
}
#define UNALIGNED_READ(p_val, p_buf) \
do { \
memcpy((p_val), (p_buf), sizeof(*(p_val))); \
(p_buf) += sizeof(*(p_val)); \
} while(0)
static py_i64 pkl__read_int(const unsigned char** p) {
PickleOp op = (PickleOp) * *p;
(*p)++;
switch(op) {
// clang-format off
case PKL_INT_0: return 0; case PKL_INT_1: return 1; case PKL_INT_2: return 2; case PKL_INT_3: return 3;
case PKL_INT_4: return 4; case PKL_INT_5: return 5; case PKL_INT_6: return 6; case PKL_INT_7: return 7;
case PKL_INT_8: return 8; case PKL_INT_9: return 9; case PKL_INT_10: return 10; case PKL_INT_11: return 11;
case PKL_INT_12: return 12; case PKL_INT_13: return 13; case PKL_INT_14: return 14; case PKL_INT_15: return 15;
// clang-format on
case PKL_INT8: {
int8_t val;
UNALIGNED_READ(&val, *p);
return val;
}
case PKL_INT16: {
int16_t val;
UNALIGNED_READ(&val, *p);
return val;
}
case PKL_INT32: {
int32_t val;
UNALIGNED_READ(&val, *p);
return val;
}
case PKL_INT64: {
int64_t val;
UNALIGNED_READ(&val, *p);
return val;
}
default: c11__abort("pkl__read_int(): invalid op: %d", op);
}
}
static bool pickle_loads(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_bytes);
int size;
const unsigned char* data = py_tobytes(argv, &size);
return py_pickle_loads(data, size);
}
static bool pickle_dumps(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_pickle_dumps(argv);
}
void pk__add_module_pickle() {
py_Ref mod = py_newmodule("pickle");
py_bindfunc(mod, "loads", pickle_loads);
py_bindfunc(mod, "dumps", pickle_dumps);
}
static bool pkl__write_object(PickleObject* buf, py_TValue* obj);
static bool pkl__write_array(PickleObject* buf, PickleOp op, py_TValue* arr, int length) {
for(int i = 0; i < length; i++) {
bool ok = pkl__write_object(buf, arr + i);
if(!ok) return false;
}
pkl__emit_op(buf, op);
pkl__emit_int(buf, length);
return true;
}
static bool pkl__write_dict_kv(py_Ref k, py_Ref v, void* ctx) {
PickleObject* buf = (PickleObject*)ctx;
if(!pkl__write_object(buf, k)) return false;
if(!pkl__write_object(buf, v)) return false;
return true;
}
static bool pkl__try_memo(PickleObject* buf, PyObject* memo_key) {
int index = c11_smallmap_p2i__get(&buf->memo, memo_key, -1);
if(index != -1) {
pkl__emit_op(buf, PKL_MEMO_GET);
pkl__emit_int(buf, index);
return true;
}
return false;
}
static void pkl__store_memo(PickleObject* buf, PyObject* memo_key) {
int index = buf->memo.length;
c11_smallmap_p2i__set(&buf->memo, memo_key, index);
pkl__emit_op(buf, PKL_MEMO_SET);
pkl__emit_int(buf, index);
}
static bool _check_function(Function* f) {
if(!f->module) return ValueError("cannot pickle function (!f->module)");
if(f->closure) return ValueError("cannot pickle function with closure");
if(f->decl->nested) return ValueError("cannot pickle nested function");
c11_string* name = f->decl->code.name;
if(name->size == 0) return ValueError("cannot pickle function with empty name");
if(name->data[0] == '<') return ValueError("cannot pickle anonymous function");
return true;
}
static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
switch(obj->type) {
case tp_nil: {
return ValueError("'nil' object is not picklable");
}
case tp_NoneType: {
pkl__emit_op(buf, PKL_NONE);
return true;
}
case tp_ellipsis: {
pkl__emit_op(buf, PKL_ELLIPSIS);
return true;
}
case tp_int: {
py_i64 val = obj->_i64;
pkl__emit_int(buf, val);
return true;
}
case tp_float: {
py_f64 val = obj->_f64;
float val32 = (float)val;
if(val == val32) {
pkl__emit_op(buf, PKL_FLOAT32);
PickleObject__write_bytes(buf, &val32, 4);
} else {
pkl__emit_op(buf, PKL_FLOAT64);
PickleObject__write_bytes(buf, &val, 8);
}
return true;
}
case tp_bool: {
bool val = obj->_bool;
pkl__emit_op(buf, val ? PKL_TRUE : PKL_FALSE);
return true;
}
case tp_str: {
if(obj->is_ptr && pkl__try_memo(buf, obj->_obj)) return true;
pkl__emit_op(buf, PKL_STRING);
c11_sv sv = py_tosv(obj);
pkl__emit_int(buf, sv.size);
PickleObject__write_bytes(buf, sv.data, sv.size);
if(obj->is_ptr) pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_bytes: {
if(pkl__try_memo(buf, obj->_obj)) return true;
pkl__emit_op(buf, PKL_BYTES);
int size;
unsigned char* data = py_tobytes(obj, &size);
pkl__emit_int(buf, size);
PickleObject__write_bytes(buf, data, size);
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_list: {
if(pkl__try_memo(buf, obj->_obj)) return true;
bool ok = pkl__write_array(buf, PKL_BUILD_LIST, py_list_data(obj), py_list_len(obj));
if(!ok) return false;
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_tuple: {
if(pkl__try_memo(buf, obj->_obj)) return true;
bool ok = pkl__write_array(buf, PKL_BUILD_TUPLE, py_tuple_data(obj), py_tuple_len(obj));
if(!ok) return false;
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_dict: {
if(pkl__try_memo(buf, obj->_obj)) return true;
bool ok = py_dict_apply(obj, pkl__write_dict_kv, (void*)buf);
if(!ok) return false;
pkl__emit_op(buf, PKL_BUILD_DICT);
pkl__emit_int(buf, py_dict_len(obj));
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_vec2: {
c11_vec2 val = py_tovec2(obj);
pkl__emit_op(buf, PKL_VEC2);
PickleObject__write_bytes(buf, &val, sizeof(c11_vec2));
return true;
}
case tp_vec3: {
c11_vec3 val = py_tovec3(obj);
pkl__emit_op(buf, PKL_VEC3);
PickleObject__write_bytes(buf, &val, sizeof(c11_vec3));
return true;
}
case tp_vec2i: {
c11_vec2i val = py_tovec2i(obj);
pkl__emit_op(buf, PKL_VEC2I);
pkl__emit_int(buf, val.x);
pkl__emit_int(buf, val.y);
return true;
}
case tp_vec3i: {
c11_vec3i val = py_tovec3i(obj);
pkl__emit_op(buf, PKL_VEC3I);
pkl__emit_int(buf, val.x);
pkl__emit_int(buf, val.y);
pkl__emit_int(buf, val.z);
return true;
}
case tp_type: {
pkl__emit_op(buf, PKL_TYPE);
py_Type type = py_totype(obj);
buf->used_types[type] = true;
pkl__emit_int(buf, type);
return true;
}
case tp_module: {
if(pkl__try_memo(buf, obj->_obj)) return true;
py_ModuleInfo* mi = py_touserdata(obj);
pkl__emit_op(buf, PKL_IMPORT_PATH);
pkl__emit_cstr(buf, mi->path->data);
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_function: {
if(pkl__try_memo(buf, obj->_obj)) return true;
Function* f = py_touserdata(obj);
if(!_check_function(f)) return false;
c11_string* name = f->decl->code.name;
if(f->clazz) {
// NOTE: copied from logic of `case tp_type:`
pkl__emit_op(buf, PKL_TYPE);
py_TypeInfo* ti = PyObject__userdata(f->clazz);
py_Type type = ti->index;
buf->used_types[type] = true;
pkl__emit_int(buf, type);
} else {
if(!pkl__write_object(buf, f->module)) return false;
}
pkl__emit_op(buf, PKL_GETATTR);
pkl__emit_cstr(buf, name->data);
pkl__store_memo(buf, obj->_obj);
return true;
}
case tp_boundmethod: {
py_Ref self = py_getslot(obj, 0);
if(!py_istype(self, tp_type)) {
return ValueError("tp_boundmethod: !py_istype(self, tp_type)");
}
py_Ref func = py_getslot(obj, 1);
if(!py_istype(func, tp_function)) {
return ValueError("tp_boundmethod: !py_istype(func, tp_function)");
}
Function* f = py_touserdata(func);
if(!_check_function(f)) return false;
c11_string* name = f->decl->code.name;
// NOTE: copied from logic of `case tp_type:`
pkl__emit_op(buf, PKL_TYPE);
py_Type type = py_totype(self);
buf->used_types[type] = true;
pkl__emit_int(buf, type);
pkl__emit_op(buf, PKL_GETATTR);
pkl__emit_cstr(buf, name->data);
return true;
}
case tp_array2d: {
if(pkl__try_memo(buf, obj->_obj)) return true;
c11_array2d* arr = py_touserdata(obj);
for(int i = 0; i < arr->header.numel; i++) {
if(arr->data[i].is_ptr)
return TypeError(
"'array2d' object is not picklable because it contains heap-allocated objects");
buf->used_types[arr->data[i].type] = true;
}
pkl__emit_op(buf, PKL_ARRAY2D);
pkl__emit_int(buf, arr->header.n_cols);
pkl__emit_int(buf, arr->header.n_rows);
PickleObject__write_bytes(buf, arr->data, arr->header.numel * sizeof(py_TValue));
pkl__store_memo(buf, obj->_obj);
return true;
}
default: {
if(!obj->is_ptr) {
pkl__emit_op(buf, PKL_TVALUE);
PickleObject__write_bytes(buf, obj, sizeof(py_TValue));
buf->used_types[obj->type] = true;
return true;
}
// try memo for `is_ptr=true` objects
if(pkl__try_memo(buf, obj->_obj)) return true;
py_TypeInfo* ti = pk_typeinfo(obj->type);
py_Ref f_reduce = py_tpfindmagic(obj->type, __reduce__);
if(f_reduce != NULL) {
if(!py_call(f_reduce, 1, obj)) return false;
// expected: (callable, args)
py_Ref reduced = py_retval();
if(!py_istuple(reduced)) { return TypeError("__reduce__ must return a tuple"); }
if(py_tuple_len(reduced) != 2) {
return TypeError("__reduce__ must return a tuple of length 2");
}
if(!pkl__write_object(buf, py_tuple_getitem(reduced, 0))) return false;
pkl__emit_op(buf, PKL_NIL);
py_Ref args_tuple = py_tuple_getitem(reduced, 1);
int args_length = py_tuple_len(args_tuple);
for(int i = 0; i < args_length; i++) {
if(!pkl__write_object(buf, py_tuple_getitem(args_tuple, i))) return false;
}
pkl__emit_op(buf, PKL_CALL);
pkl__emit_int(buf, args_length);
// store memo
pkl__store_memo(buf, obj->_obj);
return true;
}
if(ti->is_python) {
NameDict* dict = PyObject__dict(obj->_obj);
for(int i = dict->capacity - 1; i >= 0; i--) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
if(!pkl__write_object(buf, &kv->value)) return false;
}
pkl__emit_op(buf, PKL_OBJECT);
pkl__emit_int(buf, obj->type);
buf->used_types[obj->type] = true;
pkl__emit_int(buf, dict->length);
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
c11_sv field = py_name2sv(kv->key);
// include '\0'
PickleObject__write_bytes(buf, field.data, field.size + 1);
}
// store memo
pkl__store_memo(buf, obj->_obj);
return true;
}
return TypeError("'%t' object is not picklable", obj->type);
}
}
c11__unreachable();
}
bool py_pickle_dumps(py_Ref val) {
PickleObject buf;
PickleObject__ctor(&buf);
bool ok = pkl__write_object(&buf, val);
if(!ok) {
PickleObject__dtor(&buf);
return false;
}
pkl__emit_op(&buf, PKL_EOF);
return PickleObject__py_submit(&buf, py_retval());
}
static py_Type pkl__header_find_type(c11_sv path) {
int sep_index = c11_sv__rindex(path, '.');
if(sep_index == -1) return py_gettype(NULL, py_namev(path));
c11_sv mod_name = c11_sv__slice2(path, 0, sep_index);
c11_sv name = c11_sv__slice(path, sep_index + 1);
char buf[PK_MAX_MODULE_PATH_LEN + 1];
memcpy(buf, mod_name.data, mod_name.size);
buf[mod_name.size] = '\0';
return py_gettype(buf, py_namev(name));
}
static c11_sv pkl__header_read_sv(const unsigned char** p, char sep) {
c11_sv text;
text.data = (const char*)*p;
const char* p_end = strchr(text.data, sep);
assert(p_end != NULL);
text.size = p_end - text.data;
*p = (const unsigned char*)p_end + 1;
return text;
}
static py_i64 pkl__header_read_int(const unsigned char** p, char sep) {
c11_sv text = pkl__header_read_sv(p, sep);
py_i64 out;
IntParsingResult res = c11__parse_uint(text, &out, 10);
assert(res == IntParsing_SUCCESS);
return out;
}
bool py_pickle_loads_body(const unsigned char* p, int memo_length, c11_smallmap_d2d* type_mapping);
bool py_pickle_loads(const unsigned char* data, int size) {
const unsigned char* p = data;
// \xf0\x9f\xa5\x95
if(size < 4 || p[0] != 240 || p[1] != 159 || p[2] != 165 || p[3] != 149)
return ValueError("invalid pickle data");
p += 4;
c11_smallmap_d2d type_mapping;
c11_smallmap_d2d__ctor(&type_mapping);
while(true) {
if(*p == '\n') {
p++;
break;
}
py_Type type = pkl__header_read_int(&p, '(');
c11_sv path = pkl__header_read_sv(&p, ')');
py_Type new_type = pkl__header_find_type(path);
if(new_type == 0) {
c11_smallmap_d2d__dtor(&type_mapping);
return ImportError("cannot find type '%v'", path);
}
if(type != new_type) c11_smallmap_d2d__set(&type_mapping, type, new_type);
}
int memo_length = pkl__header_read_int(&p, '\n');
bool ok = py_pickle_loads_body(p, memo_length, &type_mapping);
c11_smallmap_d2d__dtor(&type_mapping);
return ok;
}
static py_Type pkl__fix_type(py_Type type, c11_smallmap_d2d* type_mapping) {
int new_type = c11_smallmap_d2d__get(type_mapping, type, -1);
if(new_type != -1) return (py_Type)new_type;
return type;
}
bool py_pickle_loads_body(const unsigned char* p, int memo_length, c11_smallmap_d2d* type_mapping) {
py_StackRef p0 = py_peek(0);
py_Ref p_memo = py_newtuple(py_pushtmp(), memo_length);
while(true) {
PickleOp op = (PickleOp)*p;
p++;
switch(op) {
case PKL_MEMO_GET: {
int index = pkl__read_int(&p);
py_Ref val = &p_memo[index];
assert(!py_isnil(val));
py_push(val);
break;
}
case PKL_MEMO_SET: {
int index = pkl__read_int(&p);
p_memo[index] = *py_peek(-1);
break;
}
case PKL_NIL: {
py_pushnil();
break;
}
case PKL_NONE: {
py_pushnone();
break;
}
case PKL_ELLIPSIS: {
py_newellipsis(py_pushtmp());
break;
}
// clang-format off
case PKL_INT_0: case PKL_INT_1: case PKL_INT_2: case PKL_INT_3:
case PKL_INT_4: case PKL_INT_5: case PKL_INT_6: case PKL_INT_7:
case PKL_INT_8: case PKL_INT_9: case PKL_INT_10: case PKL_INT_11:
case PKL_INT_12: case PKL_INT_13: case PKL_INT_14: case PKL_INT_15: {
py_newint(py_pushtmp(), op - PKL_INT_0);
break;
}
// clang-format on
case PKL_INT8: {
int8_t val;
UNALIGNED_READ(&val, p);
py_newint(py_pushtmp(), val);
break;
}
case PKL_INT16: {
int16_t val;
UNALIGNED_READ(&val, p);
py_newint(py_pushtmp(), val);
break;
}
case PKL_INT32: {
int32_t val;
UNALIGNED_READ(&val, p);
py_newint(py_pushtmp(), val);
break;
}
case PKL_INT64: {
int64_t val;
UNALIGNED_READ(&val, p);
py_newint(py_pushtmp(), val);
break;
}
case PKL_FLOAT32: {
float val;
UNALIGNED_READ(&val, p);
py_newfloat(py_pushtmp(), val);
break;
}
case PKL_FLOAT64: {
double val;
UNALIGNED_READ(&val, p);
py_newfloat(py_pushtmp(), val);
break;
}
case PKL_TRUE: {
py_newbool(py_pushtmp(), true);
break;
}
case PKL_FALSE: {
py_newbool(py_pushtmp(), false);
break;
}
case PKL_STRING: {
int size = pkl__read_int(&p);
char* dst = py_newstrn(py_pushtmp(), size);
memcpy(dst, p, size);
p += size;
break;
}
case PKL_BYTES: {
int size = pkl__read_int(&p);
unsigned char* dst = py_newbytes(py_pushtmp(), size);
memcpy(dst, p, size);
p += size;
break;
}
case PKL_BUILD_LIST: {
int length = pkl__read_int(&p);
py_Ref val = py_retval();
py_newlistn(val, length);
for(int i = length - 1; i >= 0; i--) {
py_StackRef item = py_peek(-1);
py_list_setitem(val, i, item);
py_pop();
}
py_push(val);
break;
}
case PKL_BUILD_TUPLE: {
int length = pkl__read_int(&p);
py_Ref val = py_retval();
py_Ref p = py_newtuple(val, length);
for(int i = length - 1; i >= 0; i--) {
p[i] = *py_peek(-1);
py_pop();
}
py_push(val);
break;
}
case PKL_BUILD_DICT: {
int length = pkl__read_int(&p);
py_Ref val = py_pushtmp();
py_newdict(val);
py_StackRef begin = py_peek(-1) - 2 * length;
py_StackRef end = py_peek(-1);
for(py_StackRef i = begin; i < end; i += 2) {
py_StackRef k = i;
py_StackRef v = i + 1;
bool ok = py_dict_setitem(val, k, v);
if(!ok) return false;
}
py_assign(py_retval(), val);
py_shrink(2 * length + 1);
py_push(py_retval());
break;
}
case PKL_VEC2: {
c11_vec2 val;
UNALIGNED_READ(&val, p);
py_newvec2(py_pushtmp(), val);
break;
}
case PKL_VEC3: {
c11_vec3 val;
UNALIGNED_READ(&val, p);
py_newvec3(py_pushtmp(), val);
break;
}
case PKL_VEC2I: {
c11_vec2i val;
val.x = pkl__read_int(&p);
val.y = pkl__read_int(&p);
py_newvec2i(py_pushtmp(), val);
break;
}
case PKL_VEC3I: {
c11_vec3i val;
val.x = pkl__read_int(&p);
val.y = pkl__read_int(&p);
val.z = pkl__read_int(&p);
py_newvec3i(py_pushtmp(), val);
break;
}
case PKL_TYPE: {
py_Type type = (py_Type)pkl__read_int(&p);
type = pkl__fix_type(type, type_mapping);
py_push(py_tpobject(type));
break;
}
case PKL_ARRAY2D: {
int n_cols = pkl__read_int(&p);
int n_rows = pkl__read_int(&p);
c11_array2d* arr = c11_newarray2d(py_pushtmp(), n_cols, n_rows);
int total_size = arr->header.numel * sizeof(py_TValue);
memcpy(arr->data, p, total_size);
for(int i = 0; i < arr->header.numel; i++) {
arr->data[i].type = pkl__fix_type(arr->data[i].type, type_mapping);
}
p += total_size;
break;
}
case PKL_IMPORT_PATH: {
const char* path = pkl__read_cstr(&p);
int res = py_import(path);
if(res == -1) return false;
if(res == 0) return ImportError("No module named '%s'", path);
py_push(py_retval());
break;
}
case PKL_GETATTR: {
const char* name = pkl__read_cstr(&p);
py_Ref obj = py_peek(-1);
if(!py_getattr(obj, py_name(name))) return false;
py_pop();
py_push(py_retval());
break;
}
case PKL_TVALUE: {
py_TValue* tmp = py_pushtmp();
memcpy(tmp, p, sizeof(py_TValue));
tmp->type = pkl__fix_type(tmp->type, type_mapping);
p += sizeof(py_TValue);
break;
}
case PKL_CALL: {
int argc = pkl__read_int(&p);
if(!py_vectorcall(argc, 0)) return false;
py_push(py_retval());
break;
}
case PKL_OBJECT: {
py_Type type = (py_Type)pkl__read_int(&p);
type = pkl__fix_type(type, type_mapping);
py_newobject(py_retval(), type, -1, 0);
NameDict* dict = PyObject__dict(py_retval()->_obj);
int dict_length = pkl__read_int(&p);
for(int i = 0; i < dict_length; i++) {
py_StackRef value = py_peek(-1);
c11_sv field = {(const char*)p, strlen((const char*)p)};
NameDict__set(dict, py_namev(field), value);
py_pop();
p += field.size + 1;
}
py_push(py_retval());
break;
}
case PKL_EOF: {
// [memo, obj]
if(py_peek(0) - p0 != 2) return ValueError("invalid pickle data");
py_assign(py_retval(), py_peek(-1));
py_shrink(2);
return true;
}
default: c11__unreachable();
}
}
c11__unreachable();
}
static bool PickleObject__py_submit(PickleObject* self, py_OutRef out) {
c11_sbuf cleartext;
c11_sbuf__ctor(&cleartext);
c11_sbuf__write_cstr(&cleartext, "\xf0\x9f\xa5\x95");
// line 1: type mapping
for(py_Type type = 0; type < self->used_types_length; type++) {
if(self->used_types[type]) {
c11_sbuf__write_int(&cleartext, type);
c11_sbuf__write_char(&cleartext, '(');
c11_sbuf__write_type_path(&cleartext, type);
c11_sbuf__write_char(&cleartext, ')');
}
}
c11_sbuf__write_char(&cleartext, '\n');
// line 2: memo length
c11_sbuf__write_int(&cleartext, self->memo.length);
c11_sbuf__write_char(&cleartext, '\n');
// -------------------------------------------------- //
c11_string* header = c11_sbuf__submit(&cleartext);
int total_size = header->size + self->codes.length;
unsigned char* p = py_newbytes(py_retval(), total_size);
memcpy(p, header->data, header->size);
memcpy(p + header->size, self->codes.data, self->codes.length);
c11_string__delete(header);
PickleObject__dtor(self);
return true;
}
#undef UNALIGNED_READ
// src/modules\picoterm.c
#include <stdio.h>
const char* c11__u32_east_asian_width(int c);
static int c11__wcwidth(int c) {
if(c >= 32 && c < 0x7f) return 1;
if(c < 32) return 0;
const char* w = c11__u32_east_asian_width(c);
bool fullwidth = (w[0] == 'F' && w[1] == '\0') || (w[0] == 'W' && w[1] == '\0');
return fullwidth ? 2 : 1;
}
static bool picoterm_enable_full_buffering_mode(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
static char buf[1024 * 32]; // 32KB
setvbuf(stdout, buf, _IOFBF, sizeof(buf));
py_newnone(py_retval());
return true;
}
// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
typedef struct {
c11_sv text;
char suffix;
} AnsiEscapedToken;
static bool split_ansi_escaped_string(c11_sv sv, c11_vector* out_tokens);
static bool picoterm_split_ansi_escaped_string(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv s = py_tosv(argv);
c11_vector /*T=AnsiEscapedToken*/ tokens;
c11_vector__ctor(&tokens, sizeof(AnsiEscapedToken));
if(!split_ansi_escaped_string(s, &tokens)) {
c11_vector__dtor(&tokens);
return ValueError("invalid ANSI escape sequences");
}
py_newlistn(py_retval(), tokens.length);
for(int i = 0; i < tokens.length; i++) {
AnsiEscapedToken t = c11__getitem(AnsiEscapedToken, &tokens, i);
py_ItemRef item = py_list_getitem(py_retval(), i);
py_newstrv(item, t.text);
}
c11_vector__dtor(&tokens);
return true;
}
static bool picoterm_wcwidth(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
int c = py_toint(py_arg(0));
py_newint(py_retval(), c11__wcwidth(c));
return true;
}
static bool picoterm_wcswidth(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv sv = py_tosv(py_arg(0));
c11_vector /*T=AnsiEscapedToken*/ tokens;
c11_vector__ctor(&tokens, sizeof(AnsiEscapedToken));
if(!split_ansi_escaped_string(sv, &tokens)) {
c11_vector__dtor(&tokens);
return ValueError("invalid ANSI escape sequences");
}
int total_width = 0;
for(int i = 0; i < tokens.length; i++) {
AnsiEscapedToken* p_token = c11__at(AnsiEscapedToken, &tokens, i);
if(p_token->suffix != '\0') continue;
const char* curr_char = p_token->text.data;
const char* end_char = p_token->text.data + p_token->text.size;
while(curr_char < end_char) {
unsigned char c = *curr_char;
int u8bytes = c11__u8_header(c, true);
if(u8bytes == 0) return ValueError("invalid utf-8 header: %d", (int)c);
int value = c11__u8_value(u8bytes, curr_char);
total_width += c11__wcwidth(value);
curr_char += u8bytes;
}
}
c11_vector__dtor(&tokens);
py_newint(py_retval(), total_width);
return true;
}
static bool picoterm_sscanf(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_str);
PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_list);
const char* input = py_tostr(py_arg(0));
const char* format = py_tostr(py_arg(1));
py_Ref output_list = py_arg(2);
py_list_clear(output_list);
const char* p1 = input;
const char* p2 = format;
while(*p1 != '\0' && *p2 != '\0') {
if(*p2 == '%') {
p2++;
if(*p2 == 'd' || *p2 == 'i') {
bool negative = false;
if(*p1 == '-') {
negative = true;
p1++;
}
const char* start = p1;
while(*p1 >= '0' && *p1 <= '9')
p1++;
c11_sv num_sv = {.data = start, .size = p1 - start};
if(num_sv.size == 0) break;
int64_t value = 0;
IntParsingResult res = c11__parse_uint(num_sv, &value, 10);
if(res != IntParsing_SUCCESS) break;
if(negative) value = -value;
py_ItemRef item = py_list_emplace(output_list);
py_newint(item, value);
p2++;
} else {
return ValueError("unsupported format specifier: %%%c", *p2);
}
} else {
if(*p1 != *p2) break;
p1++;
p2++;
}
}
py_newbool(py_retval(), *p2 == '\0');
return true;
}
void pk__add_module_picoterm() {
py_Ref mod = py_newmodule("picoterm");
py_bindfunc(mod, "enable_full_buffering_mode", picoterm_enable_full_buffering_mode);
py_bindfunc(mod, "split_ansi_escaped_string", picoterm_split_ansi_escaped_string);
py_bindfunc(mod, "wcwidth", picoterm_wcwidth);
py_bindfunc(mod, "wcswidth", picoterm_wcswidth);
py_bindfunc(mod, "sscanf", picoterm_sscanf);
}
static bool split_ansi_escaped_string(c11_sv sv, c11_vector* out_tokens) {
const char* p = sv.data;
int i = 0;
while(i < sv.size) {
if(p[i] == '\x1b') {
i++; // skip '\x1b'
if(i >= sv.size || p[i] != '[') {
return false; // invalid escape sequence
}
int esc_start = i - 1;
i++; // skip '['
c11_sv content;
content.data = p + i;
while(i < sv.size && !((p[i] >= 'A' && p[i] <= 'Z') || (p[i] >= 'a' && p[i] <= 'z'))) {
i++;
}
content.size = p + i - content.data;
if(i >= sv.size) {
return false; // invalid escape sequence
}
char suffix = p[i];
i++; // skip suffix
AnsiEscapedToken token;
token.text = (c11_sv){p + esc_start, i - esc_start};
token.suffix = suffix;
c11_vector__push(AnsiEscapedToken, out_tokens, token);
} else if(p[i] == '\n') {
AnsiEscapedToken token;
token.text = (c11_sv){p + i, 1};
token.suffix = '\n';
c11_vector__push(AnsiEscapedToken, out_tokens, token);
i++;
} else {
int text_start = i;
while(i < sv.size && p[i] != '\x1b' && p[i] != '\n') {
i++;
}
AnsiEscapedToken token;
token.text = (c11_sv){p + text_start, i - text_start};
token.suffix = '\0';
c11_vector__push(AnsiEscapedToken, out_tokens, token);
}
}
return true;
}
// src/modules\pkpy.c
#include <time.h>
#define DEF_TVALUE_METHODS(T, Field) \
static bool TValue_##T##__new__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
PY_CHECK_ARG_TYPE(0, tp_type); \
PY_CHECK_ARG_TYPE(1, tp_##T); \
*py_retval() = (py_TValue){ \
.type = py_totype(&argv[0]), \
.is_ptr = false, \
.Field = py_to##T(&argv[1]), \
}; \
return true; \
} \
static bool TValue_##T##_value(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
py_new##T(py_retval(), argv->Field); \
return true; \
} \
static bool TValue_##T##__repr__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
py_newstr(py_retval(), "<TValue_" #T " object>"); \
return true; \
}
DEF_TVALUE_METHODS(int, _i64)
DEF_TVALUE_METHODS(float, _f64)
DEF_TVALUE_METHODS(vec2, _vec2)
DEF_TVALUE_METHODS(vec2i, _vec2i)
static bool pkpy_memory_usage(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
py_i64 size = MultiPool__total_allocated_bytes(&heap->small_objects);
size += heap->large_total_size;
size += sizeof(VM);
py_newint(py_retval(), size);
return true;
}
static bool pkpy_memory_usage_info(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap;
c11_string* small_objects_usage = MultiPool__summary(&heap->small_objects);
int large_object_count = heap->large_objects.length;
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, "== pre-allocated ==\n");
double vm_size_mb = sizeof(VM) / 1024.0 / 1024.0;
c11_sbuf__write_cstr(&buf, "VM: ");
c11_sbuf__write_f64(&buf, vm_size_mb, 2);
c11_sbuf__write_cstr(&buf, " MB\n");
c11_sbuf__write_cstr(&buf, "== heap.small_objects ==\n");
c11_sbuf__write_cstr(&buf, small_objects_usage->data);
c11_sbuf__write_cstr(&buf, "== heap.large_objects ==\n");
pk_sprintf(&buf, "len(large_objects)=%d\n", large_object_count);
double large_total_size_mb = (size_t)(heap->large_total_size / 1024) / 1024.0;
c11_sbuf__write_cstr(&buf, "Total: ~");
c11_sbuf__write_f64(&buf, large_total_size_mb, 2);
c11_sbuf__write_cstr(&buf, " MB\n");
c11_sbuf__write_cstr(&buf, "== heap.gc ==\n");
pk_sprintf(&buf, "gc_counter=%d\n", heap->gc_counter);
pk_sprintf(&buf, "gc_threshold=%d", heap->gc_threshold);
// c11_sbuf__write_cstr(&buf, "== vm.pool_frame ==\n");
c11_sbuf__py_submit(&buf, py_retval());
c11_string__delete(small_objects_usage);
return true;
}
static bool pkpy_currentvm(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_newint(py_retval(), py_currentvm());
return true;
}
#if PK_ENABLE_WATCHDOG
void py_watchdog_begin(py_i64 timeout) {
WatchdogInfo* info = &pk_current_vm->watchdog_info;
info->max_reset_time = clock() + (timeout * (CLOCKS_PER_SEC / 1000));
}
void py_watchdog_end() {
WatchdogInfo* info = &pk_current_vm->watchdog_info;
info->max_reset_time = 0;
}
static bool pkpy_watchdog_begin(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
py_watchdog_begin(py_toint(argv));
py_newnone(py_retval());
return true;
}
static bool pkpy_watchdog_end(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_watchdog_end();
py_newnone(py_retval());
return true;
}
#endif
#if PK_ENABLE_THREADS
typedef struct c11_ComputeThread c11_ComputeThread;
typedef struct {
c11_ComputeThread* self;
char* eval_src;
unsigned char* args_data;
int args_size;
unsigned char* kwargs_data;
int kwargs_size;
} ComputeThreadJobCall;
typedef struct {
c11_ComputeThread* self;
char* source;
enum py_CompileMode mode;
} ComputeThreadJobExec;
static void ComputeThreadJobCall__dtor(void* arg) {
ComputeThreadJobCall* self = arg;
PK_FREE(self->eval_src);
PK_FREE(self->args_data);
PK_FREE(self->kwargs_data);
}
static void ComputeThreadJobExec__dtor(void* arg) {
ComputeThreadJobExec* self = arg;
PK_FREE(self->source);
}
typedef struct c11_ComputeThread {
int vm_index;
atomic_bool is_done;
unsigned char* last_retval_data;
int last_retval_size;
char* last_error;
c11_thrd_t thread;
void* job;
void (*job_dtor)(void*);
} c11_ComputeThread;
static void
c11_ComputeThread__reset_job(c11_ComputeThread* self, void* job, void (*job_dtor)(void*)) {
if(self->job) {
self->job_dtor(self->job);
PK_FREE(self->job);
}
self->job = job;
self->job_dtor = job_dtor;
}
static bool _pk_compute_thread_flags[16];
static void c11_ComputeThread__dtor(c11_ComputeThread* self) {
if(!atomic_load(&self->is_done)) {
c11__abort("ComputeThread(%d) is not done yet!! But the object was deleted.",
self->vm_index);
}
if(self->last_retval_data) PK_FREE(self->last_retval_data);
if(self->last_error) PK_FREE(self->last_error);
c11_ComputeThread__reset_job(self, NULL, NULL);
_pk_compute_thread_flags[self->vm_index] = false;
}
static void c11_ComputeThread__on_job_begin(c11_ComputeThread* self) {
if(self->last_retval_data) {
PK_FREE(self->last_retval_data);
self->last_retval_data = NULL;
self->last_retval_size = 0;
}
if(self->last_error) {
PK_FREE(self->last_error);
self->last_error = NULL;
}
py_switchvm(self->vm_index);
}
static bool ComputeThread__new__(int argc, py_Ref argv) {
c11_ComputeThread* self =
py_newobject(py_retval(), py_totype(argv), 0, sizeof(c11_ComputeThread));
self->vm_index = 0;
atomic_store(&self->is_done, true);
self->last_retval_data = NULL;
self->last_retval_size = 0;
self->last_error = NULL;
self->job = NULL;
self->job_dtor = NULL;
return true;
}
static bool ComputeThread__init__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_int);
c11_ComputeThread* self = py_touserdata(py_arg(0));
int index = py_toint(py_arg(1));
if(index >= 1 && index < 16) {
if(_pk_compute_thread_flags[index]) {
return ValueError("vm_index %d is already in use", index);
}
_pk_compute_thread_flags[index] = true;
self->vm_index = index;
} else {
return ValueError("vm_index %d is out of range", index);
}
py_newnone(py_retval());
return true;
}
static bool ComputeThread_is_done(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_ComputeThread* self = py_touserdata(argv);
bool value = atomic_load(&self->is_done);
py_newbool(py_retval(), value);
return true;
}
static bool ComputeThread_wait_for_done(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_ComputeThread* self = py_touserdata(argv);
while(!atomic_load(&self->is_done)) {
c11_thrd__yield();
}
py_newnone(py_retval());
return true;
}
static bool ComputeThread_last_error(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_ComputeThread* self = py_touserdata(argv);
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
if(self->last_error) {
py_newstr(py_retval(), self->last_error);
} else {
py_newnone(py_retval());
}
return true;
}
static bool ComputeThread_last_retval(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_ComputeThread* self = py_touserdata(argv);
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
if(self->last_retval_data == NULL) return ValueError("no retval available");
return py_pickle_loads(self->last_retval_data, self->last_retval_size);
}
static c11_thrd_retval_t ComputeThreadJob_call(void* arg) {
ComputeThreadJobCall* job = arg;
c11_ComputeThread* self = job->self;
c11_ComputeThread__on_job_begin(self);
py_StackRef p0 = py_peek(0);
if(!py_pusheval(job->eval_src, NULL)) goto __ERROR;
// [callable]
if(!py_pickle_loads(job->args_data, job->args_size)) goto __ERROR;
py_push(py_retval());
// [callable, args]
if(!py_pickle_loads(job->kwargs_data, job->kwargs_size)) goto __ERROR;
py_push(py_retval());
// [callable, args, kwargs]
if(!py_smarteval("_0(*_1, **_2)", NULL, py_peek(-3), py_peek(-2), py_peek(-1))) goto __ERROR;
py_shrink(3);
if(!py_pickle_dumps(py_retval())) goto __ERROR;
int retval_size;
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
self->last_retval_data = c11_memdup(retval_data, retval_size);
self->last_retval_size = retval_size;
atomic_store(&self->is_done, true);
return (c11_thrd_retval_t)0;
__ERROR:
self->last_error = py_formatexc();
atomic_store(&self->is_done, true);
py_clearexc(p0);
py_newnone(py_retval());
return (c11_thrd_retval_t)0;
}
static c11_thrd_retval_t ComputeThreadJob_exec(void* arg) {
ComputeThreadJobExec* job = arg;
c11_ComputeThread* self = job->self;
c11_ComputeThread__on_job_begin(self);
py_StackRef p0 = py_peek(0);
if(!py_exec(job->source, "<job>", job->mode, NULL)) goto __ERROR;
if(!py_pickle_dumps(py_retval())) goto __ERROR;
int retval_size;
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
self->last_retval_data = c11_memdup(retval_data, retval_size);
self->last_retval_size = retval_size;
atomic_store(&self->is_done, true);
return (c11_thrd_retval_t)0;
__ERROR:
self->last_error = py_formatexc();
atomic_store(&self->is_done, true);
py_clearexc(p0);
return (c11_thrd_retval_t)0;
}
static bool ComputeThread_submit_exec(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1));
/**************************/
ComputeThreadJobExec* job = PK_MALLOC(sizeof(ComputeThreadJobExec));
job->self = self;
job->source = c11_strdup(source);
job->mode = EXEC_MODE;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor);
/**************************/
atomic_store(&self->is_done, false);
bool ok = c11_thrd__create(&self->thread, ComputeThreadJob_exec, job);
if(!ok) {
atomic_store(&self->is_done, true);
return OSError("thrd_create() failed");
}
py_newnone(py_retval());
return true;
}
static bool ComputeThread_submit_eval(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1));
/**************************/
ComputeThreadJobExec* job = PK_MALLOC(sizeof(ComputeThreadJobExec));
job->self = self;
job->source = c11_strdup(source);
job->mode = EVAL_MODE;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobExec__dtor);
/**************************/
atomic_store(&self->is_done, false);
bool ok = c11_thrd__create(&self->thread, ComputeThreadJob_exec, job);
if(!ok) {
atomic_store(&self->is_done, true);
return OSError("thrd_create() failed");
}
py_newnone(py_retval());
return true;
}
static bool ComputeThread_submit_call(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
c11_ComputeThread* self = py_touserdata(py_arg(0));
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
PY_CHECK_ARG_TYPE(1, tp_str);
PY_CHECK_ARG_TYPE(2, tp_tuple);
PY_CHECK_ARG_TYPE(3, tp_dict);
// eval_src
const char* eval_src = py_tostr(py_arg(1));
// *args
if(!py_pickle_dumps(py_arg(2))) return false;
int args_size;
unsigned char* args_data = py_tobytes(py_retval(), &args_size);
// *kwargs
if(!py_pickle_dumps(py_arg(3))) return false;
int kwargs_size;
unsigned char* kwargs_data = py_tobytes(py_retval(), &kwargs_size);
/**************************/
ComputeThreadJobCall* job = PK_MALLOC(sizeof(ComputeThreadJobCall));
job->self = self;
job->eval_src = c11_strdup(eval_src);
job->args_data = c11_memdup(args_data, args_size);
job->args_size = args_size;
job->kwargs_data = c11_memdup(kwargs_data, kwargs_size);
job->kwargs_size = kwargs_size;
c11_ComputeThread__reset_job(self, job, ComputeThreadJobCall__dtor);
/**************************/
atomic_store(&self->is_done, false);
bool ok = c11_thrd__create(&self->thread, ComputeThreadJob_call, job);
if(!ok) {
atomic_store(&self->is_done, true);
return OSError("thrd_create() failed");
}
py_newnone(py_retval());
return true;
}
static bool c11_ComputeThread__exec_blocked(c11_ComputeThread* self,
const char* source,
enum py_CompileMode mode) {
if(!atomic_load(&self->is_done)) return OSError("thread is not done yet");
atomic_store(&self->is_done, false);
char* err = NULL;
int old_vm_index = py_currentvm();
py_switchvm(self->vm_index);
py_StackRef p0 = py_peek(0);
if(!py_exec(source, "<job_blocked>", mode, NULL)) goto __ERROR;
if(!py_pickle_dumps(py_retval())) goto __ERROR;
int retval_size;
unsigned char* retval_data = py_tobytes(py_retval(), &retval_size);
py_switchvm(old_vm_index);
bool ok = py_pickle_loads(retval_data, retval_size);
atomic_store(&self->is_done, true);
return ok;
__ERROR:
err = py_formatexc();
py_clearexc(p0);
py_switchvm(old_vm_index);
atomic_store(&self->is_done, true);
RuntimeError("c11_ComputeThread__exec_blocked() failed:\n%s", err);
PK_FREE(err);
return false;
}
static bool ComputeThread_exec(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0));
PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1));
return c11_ComputeThread__exec_blocked(self, source, EXEC_MODE);
}
static bool ComputeThread_eval(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_ComputeThread* self = py_touserdata(py_arg(0));
PY_CHECK_ARG_TYPE(1, tp_str);
const char* source = py_tostr(py_arg(1));
return c11_ComputeThread__exec_blocked(self, source, EVAL_MODE);
}
static void pk_ComputeThread__register(py_Ref mod) {
py_Type type = py_newtype("ComputeThread", tp_object, mod, (py_Dtor)c11_ComputeThread__dtor);
py_bindmagic(type, __new__, ComputeThread__new__);
py_bindmagic(type, __init__, ComputeThread__init__);
py_bindproperty(type, "is_done", ComputeThread_is_done, NULL);
py_bindmethod(type, "wait_for_done", ComputeThread_wait_for_done);
py_bindmethod(type, "last_error", ComputeThread_last_error);
py_bindmethod(type, "last_retval", ComputeThread_last_retval);
py_bindmethod(type, "submit_exec", ComputeThread_submit_exec);
py_bindmethod(type, "submit_eval", ComputeThread_submit_eval);
py_bind(py_tpobject(type),
"submit_call(self, eval_src, *args, **kwargs)",
ComputeThread_submit_call);
py_bindmethod(type, "exec", ComputeThread_exec);
py_bindmethod(type, "eval", ComputeThread_eval);
}
#endif // PK_ENABLE_THREADS
static void pkpy_configmacros_add(py_Ref dict, const char* key, int val) {
assert(dict->type == tp_dict);
py_TValue tmp;
py_newint(&tmp, val);
py_dict_setitem_by_str(dict, key, &tmp);
}
static bool pkpy_profiler_begin(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
TraceInfo* trace_info = &pk_current_vm->trace_info;
if(trace_info->func == NULL) py_sys_settrace(LineProfiler_tracefunc, true);
if(trace_info->func != LineProfiler_tracefunc) {
return RuntimeError("LineProfiler_tracefunc() should be set as the trace function");
}
LineProfiler__begin(&pk_current_vm->line_profiler);
py_newnone(py_retval());
return true;
}
static bool pkpy_profiler_end(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
LineProfiler__end(&pk_current_vm->line_profiler);
py_newnone(py_retval());
return true;
}
static bool pkpy_profiler_reset(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
LineProfiler__reset(&pk_current_vm->line_profiler);
py_newnone(py_retval());
return true;
}
static bool pkpy_profiler_report(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
LineProfiler* lp = &pk_current_vm->line_profiler;
if(lp->enabled) LineProfiler__end(lp);
c11_string* report = LineProfiler__get_report(lp);
bool ok = py_json_loads(report->data);
c11_string__delete(report);
return ok;
}
void pk__add_module_pkpy() {
py_Ref mod = py_newmodule("pkpy");
py_Type ttype;
py_Ref TValue_dict = py_pushtmp();
py_newdict(TValue_dict);
ttype = pk_newtype("TValue_int", tp_object, mod, NULL, false, false);
py_bindmagic(ttype, __new__, TValue_int__new__);
py_bindmagic(ttype, __repr__, TValue_int__repr__);
py_bindproperty(ttype, "value", TValue_int_value, NULL);
py_dict_setitem(TValue_dict, py_tpobject(tp_int), py_tpobject(ttype));
ttype = pk_newtype("TValue_float", tp_object, mod, NULL, false, false);
py_bindmagic(ttype, __new__, TValue_float__new__);
py_bindmagic(ttype, __repr__, TValue_float__repr__);
py_bindproperty(ttype, "value", TValue_float_value, NULL);
py_dict_setitem(TValue_dict, py_tpobject(tp_float), py_tpobject(ttype));
ttype = pk_newtype("TValue_vec2", tp_object, mod, NULL, false, false);
py_bindmagic(ttype, __new__, TValue_vec2__new__);
py_bindmagic(ttype, __repr__, TValue_vec2__repr__);
py_bindproperty(ttype, "value", TValue_vec2_value, NULL);
py_dict_setitem(TValue_dict, py_tpobject(tp_vec2), py_tpobject(ttype));
ttype = pk_newtype("TValue_vec2i", tp_object, mod, NULL, false, false);
py_bindmagic(ttype, __new__, TValue_vec2i__new__);
py_bindmagic(ttype, __repr__, TValue_vec2i__repr__);
py_bindproperty(ttype, "value", TValue_vec2i_value, NULL);
py_dict_setitem(TValue_dict, py_tpobject(tp_vec2i), py_tpobject(ttype));
py_setdict(mod, py_name("TValue"), TValue_dict);
py_pop();
py_bindfunc(mod, "memory_usage", pkpy_memory_usage);
py_bindfunc(mod, "memory_usage_info", pkpy_memory_usage_info);
py_bindfunc(mod, "currentvm", pkpy_currentvm);
#if PK_ENABLE_WATCHDOG
py_bindfunc(mod, "watchdog_begin", pkpy_watchdog_begin);
py_bindfunc(mod, "watchdog_end", pkpy_watchdog_end);
#endif
#if PK_ENABLE_THREADS
pk_ComputeThread__register(mod);
#endif
py_bindfunc(mod, "profiler_begin", pkpy_profiler_begin);
py_bindfunc(mod, "profiler_end", pkpy_profiler_end);
py_bindfunc(mod, "profiler_reset", pkpy_profiler_reset);
py_bindfunc(mod, "profiler_report", pkpy_profiler_report);
py_Ref configmacros = py_emplacedict(mod, py_name("configmacros"));
py_newdict(configmacros);
pkpy_configmacros_add(configmacros, "PK_ENABLE_OS", PK_ENABLE_OS);
pkpy_configmacros_add(configmacros, "PK_ENABLE_THREADS", PK_ENABLE_THREADS);
pkpy_configmacros_add(configmacros, "PK_ENABLE_DETERMINISM", PK_ENABLE_DETERMINISM);
pkpy_configmacros_add(configmacros, "PK_ENABLE_WATCHDOG", PK_ENABLE_WATCHDOG);
pkpy_configmacros_add(configmacros, "PK_GC_MIN_THRESHOLD", PK_GC_MIN_THRESHOLD);
pkpy_configmacros_add(configmacros, "PK_VM_STACK_SIZE", PK_VM_STACK_SIZE);
}
#undef DEF_TVALUE_METHODS
// src/modules\random.c
/* https://github.com/clibs/mt19937ar
Copyright (c) 2011 Mutsuo Saito, Makoto Matsumoto, Hiroshima
University and The University of Tokyo. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the Hiroshima University nor the names of
its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
typedef struct mt19937 {
uint32_t mt[N]; /* the array for the state vector */
int mti; /* mti==N+1 means mt[N] is not initialized */
} mt19937;
/* initializes mt[N] with a seed */
static void mt19937__seed(mt19937* self, uint32_t s) {
self->mt[0] = s & 0xffffffffUL;
for(self->mti = 1; self->mti < N; self->mti++) {
self->mt[self->mti] =
(1812433253UL * (self->mt[self->mti - 1] ^ (self->mt[self->mti - 1] >> 30)) +
self->mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
self->mt[self->mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
static void mt19937__ctor(mt19937* self) { self->mti = N + 1; }
/* generates a random number on [0,0xffffffff]-interval */
static uint32_t mt19937__next_uint32(mt19937* self) {
uint32_t* mt = self->mt;
uint32_t y;
static uint32_t mag01[2] = {0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if(self->mti >= N) { /* generate N words at one time */
int kk;
if(self->mti == N + 1) { /* if init_genrand() has not been called, */
int64_t seed = time_ns();
mt19937__seed(self, (uint32_t)seed);
// seed(5489UL); /* a default initial seed is used */
}
for(kk = 0; kk < N - M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for(; kk < N - 1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
self->mti = 0;
}
y = mt[self->mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
static uint64_t mt19937__next_uint64(mt19937* self) {
return (uint64_t)mt19937__next_uint32(self) << 32 | mt19937__next_uint32(self);
}
static double mt19937__random(mt19937* self) {
// from cpython
uint32_t a = mt19937__next_uint32(self) >> 5;
uint32_t b = mt19937__next_uint32(self) >> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}
static double mt19937__uniform(mt19937* self, double a, double b) {
if(a > b) { return b + mt19937__random(self) * (a - b); }
return a + mt19937__random(self) * (b - a);
}
/* generates a random number on [a, b]-interval */
int64_t mt19937__randint(mt19937* self, int64_t a, int64_t b) {
uint64_t delta = b - a + 1;
if(delta < 0x80000000UL) {
return a + mt19937__next_uint32(self) % delta;
} else {
return a + mt19937__next_uint64(self) % delta;
}
}
static bool Random__new__(int argc, py_Ref argv) {
mt19937* ud = py_newobject(py_retval(), py_totype(argv), 0, sizeof(mt19937));
mt19937__ctor(ud);
return true;
}
static bool Random__init__(int argc, py_Ref argv) {
if(argc == 1) {
// do nothing
} else if(argc == 2) {
mt19937* ud = py_touserdata(py_arg(0));
if(!py_isnone(&argv[1])) {
PY_CHECK_ARG_TYPE(1, tp_int);
py_i64 seed = py_toint(py_arg(1));
mt19937__seed(ud, (uint32_t)seed);
}
} else {
return TypeError("Random(): expected 1 or 2 arguments, got %d");
}
py_newnone(py_retval());
return true;
}
static bool Random_seed(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
mt19937* ud = py_touserdata(py_arg(0));
py_i64 seed;
if(py_isnone(&argv[1])) {
seed = time_ns();
} else {
PY_CHECK_ARG_TYPE(1, tp_int);
seed = py_toint(py_arg(1));
}
mt19937__seed(ud, (uint32_t)seed);
py_newnone(py_retval());
return true;
}
static bool Random_random(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
mt19937* ud = py_touserdata(py_arg(0));
py_f64 res = mt19937__random(ud);
py_newfloat(py_retval(), res);
return true;
}
static bool Random_uniform(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
mt19937* ud = py_touserdata(py_arg(0));
py_f64 a, b;
if(!py_castfloat(py_arg(1), &a)) return false;
if(!py_castfloat(py_arg(2), &b)) return false;
py_f64 res = mt19937__uniform(ud, a, b);
py_newfloat(py_retval(), res);
return true;
}
static bool Random_shuffle(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_list);
mt19937* ud = py_touserdata(py_arg(0));
py_Ref L = py_arg(1);
int length = py_list_len(L);
for(int i = length - 1; i > 0; i--) {
int j = mt19937__randint(ud, 0, i);
py_list_swap(L, i, j);
}
py_newnone(py_retval());
return true;
}
static bool Random_randint(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
mt19937* ud = py_touserdata(py_arg(0));
py_i64 a = py_toint(py_arg(1));
py_i64 b = py_toint(py_arg(2));
if(a > b) return ValueError("randint(a, b): a must be less than or equal to b");
py_i64 res = mt19937__randint(ud, a, b);
py_newint(py_retval(), res);
return true;
}
static bool Random_choice(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
mt19937* ud = py_touserdata(py_arg(0));
if (py_isstr(py_arg(1))) {
c11_sv sv = py_tosv(py_arg(1));
int length = c11_sv__u8_length(sv);
if(length == 0) return IndexError("cannot choose from an empty sequence");
int index = mt19937__randint(ud, 0, length - 1);
c11_sv ch = c11_sv__u8_getitem(sv, index);
py_newstrv(py_retval(), ch);
} else {
py_TValue* p;
int length = pk_arrayview(py_arg(1), &p);
if(length == -1) return TypeError("choice(): argument must be a list, tuple or str");
if(length == 0) return IndexError("cannot choose from an empty sequence");
int index = mt19937__randint(ud, 0, length - 1);
py_assign(py_retval(), p + index);
}
return true;
}
static bool Random_choices(int argc, py_Ref argv) {
mt19937* ud = py_touserdata(py_arg(0));
py_TValue* p;
int length = pk_arrayview(py_arg(1), &p);
if(length == -1) return TypeError("choices(): argument must be a list or tuple");
if(length == 0) return IndexError("cannot choose from an empty sequence");
py_Ref weights = py_arg(2);
if(!py_checktype(py_arg(3), tp_int)) return false;
py_i64 k = py_toint(py_arg(3));
py_f64* cum_weights = PK_MALLOC(sizeof(py_f64) * length);
if(py_isnone(weights)) {
for(int i = 0; i < length; i++)
cum_weights[i] = i + 1;
} else {
py_TValue* w;
int wlen = pk_arrayview(weights, &w);
if(wlen == -1) {
PK_FREE(cum_weights);
return TypeError("choices(): weights must be a list or tuple");
}
if(wlen != length) {
PK_FREE(cum_weights);
return ValueError("len(weights) != len(population)");
}
if(!py_castfloat(&w[0], &cum_weights[0])) {
PK_FREE(cum_weights);
return false;
}
for(int i = 1; i < length; i++) {
py_f64 tmp;
if(!py_castfloat(&w[i], &tmp)) {
PK_FREE(cum_weights);
return false;
}
cum_weights[i] = cum_weights[i - 1] + tmp;
}
}
py_f64 total = cum_weights[length - 1];
if(total <= 1e-6) {
PK_FREE(cum_weights);
return ValueError("total of weights must be greater than 1e-6");
}
py_newlistn(py_retval(), k);
for(int i = 0; i < k; i++) {
py_f64 key = mt19937__random(ud) * total;
int index;
c11__lower_bound(py_f64, cum_weights, length, key, c11__less, &index);
assert(index != length);
py_list_setitem(py_retval(), i, p + index);
}
PK_FREE(cum_weights);
return true;
}
void pk__add_module_random() {
py_Ref mod = py_newmodule("random");
py_Type type = py_newtype("Random", tp_object, mod, NULL);
py_bindmagic(type, __new__, Random__new__);
py_bindmagic(type, __init__, Random__init__);
py_bindmethod(type, "seed", Random_seed);
py_bindmethod(type, "random", Random_random);
py_bindmethod(type, "uniform", Random_uniform);
py_bindmethod(type, "randint", Random_randint);
py_bindmethod(type, "shuffle", Random_shuffle);
py_bindmethod(type, "choice", Random_choice);
py_bind(py_tpobject(type), "choices(self, population, weights=None, k=1)", Random_choices);
py_Ref inst = py_pushtmp();
if(!py_tpcall(type, 0, NULL)) goto __ERROR;
py_assign(inst, py_retval());
#define ADD_INST_BOUNDMETHOD(name) \
if(!py_getattr(inst, py_name(name))) goto __ERROR; \
py_setdict(mod, py_name(name), py_retval());
ADD_INST_BOUNDMETHOD("seed");
ADD_INST_BOUNDMETHOD("random");
ADD_INST_BOUNDMETHOD("uniform");
ADD_INST_BOUNDMETHOD("randint");
ADD_INST_BOUNDMETHOD("shuffle");
ADD_INST_BOUNDMETHOD("choice");
ADD_INST_BOUNDMETHOD("choices");
#undef ADD_INST_BOUNDMETHOD
py_pop(); // pop inst
return;
__ERROR:
py_printexc();
c11__abort("failed to add module random");
}
#undef N
#undef M
#undef MATRIX_A
#undef UPPER_MASK
#undef LOWER_MASK
#undef ADD_INST_BOUNDMETHOD
void py_newRandom(py_OutRef out) {
py_Type type = py_gettype("random", py_name("Random"));
assert(type != 0);
mt19937* ud = py_newobject(out, type, 0, sizeof(mt19937));
mt19937__ctor(ud);
}
void py_Random_seed(py_Ref self, py_i64 seed) {
mt19937* ud = py_touserdata(self);
mt19937__seed(ud, (uint32_t)seed);
}
py_f64 py_Random_random(py_Ref self) {
mt19937* ud = py_touserdata(self);
return mt19937__random(ud);
}
py_f64 py_Random_uniform(py_Ref self, py_f64 a, py_f64 b) {
mt19937* ud = py_touserdata(self);
return mt19937__uniform(ud, a, b);
}
py_i64 py_Random_randint(py_Ref self, py_i64 a, py_i64 b) {
mt19937* ud = py_touserdata(self);
if(a > b) { c11__abort("randint(a, b): a must be less than or equal to b"); }
return mt19937__randint(ud, a, b);
}
// src/modules\stdc.c
#include <string.h>
#define DEF_BUILTIN_MEMORY_T(Char_, char_, tp_int_, py_newint_, py_toint_, py_i64_) \
static bool stdc_##Char_##__new__(int argc, py_Ref argv) { \
char_* ud = py_newobject(py_retval(), tp_stdc_##Char_, 0, sizeof(char_)); \
if(argc == 2) { \
PY_CHECK_ARG_TYPE(1, tp_int_); \
*ud = (char_)py_toint_(&argv[1]); \
} else if(argc > 2) { \
return TypeError("expected 1 or 2 arguments, got %d", argc); \
} \
return true; \
} \
static bool stdc_##Char_##__get_value(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
char_* ud = py_touserdata(argv); \
py_newint_(py_retval(), (py_i64_)(*ud)); \
return true; \
} \
static bool stdc_##Char_##__set_value(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
char_* ud = py_touserdata(argv); \
PY_CHECK_ARG_TYPE(1, tp_int_); \
*ud = (char_)py_toint_(&argv[1]); \
py_newnone(py_retval()); \
return true; \
} \
static bool stdc_##Char_##__read_STATIC(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
PY_CHECK_ARG_TYPE(0, tp_int); \
PY_CHECK_ARG_TYPE(1, tp_int); \
char_* p = (char_*)(intptr_t)py_toint(&argv[0]); \
int offset = py_toint(&argv[1]); \
py_newint_(py_retval(), (py_i64_)(p[offset])); \
return true; \
} \
static bool stdc_##Char_##__write_STATIC(int argc, py_Ref argv) { \
PY_CHECK_ARGC(3); \
PY_CHECK_ARG_TYPE(0, tp_int); \
PY_CHECK_ARG_TYPE(1, tp_int); \
PY_CHECK_ARG_TYPE(2, tp_int_); \
char_* p = (char_*)(intptr_t)py_toint(&argv[0]); \
int offset = py_toint(&argv[1]); \
p[offset] = (char_)py_toint_(&argv[2]); \
py_newnone(py_retval()); \
return true; \
} \
static bool stdc_##Char_##__array_STATIC(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
PY_CHECK_ARG_TYPE(0, tp_int); \
int length = py_toint(argv); \
int size = sizeof(char_) * length; \
py_newobject(py_retval(), tp_stdc_##Char_, 0, size); \
return true; \
} \
static bool stdc_##Char_##__getitem__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
char_* ud = py_touserdata(argv); \
PY_CHECK_ARG_TYPE(1, tp_int); \
int index = py_toint(&argv[1]); \
py_newint_(py_retval(), (py_i64_)(ud[index])); \
return true; \
} \
static bool stdc_##Char_##__setitem__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(3); \
char_* ud = py_touserdata(argv); \
PY_CHECK_ARG_TYPE(1, tp_int); \
PY_CHECK_ARG_TYPE(2, tp_int_); \
int index = py_toint(&argv[1]); \
ud[index] = (char_)py_toint_(&argv[2]); \
py_newnone(py_retval()); \
return true; \
} \
static void pk__bind_stdc_##Char_(py_Ref mod) { \
py_Type type = py_newtype(#Char_, tp_stdc_Memory, mod, NULL); \
py_tpsetfinal(type); \
assert(type == tp_stdc_##Char_); \
py_bindmagic(type, __new__, stdc_##Char_##__new__); \
py_bindmagic(type, __getitem__, stdc_##Char_##__getitem__); \
py_bindmagic(type, __setitem__, stdc_##Char_##__setitem__); \
py_bindproperty(type, "value", stdc_##Char_##__get_value, stdc_##Char_##__set_value); \
py_bindstaticmethod(type, "read", stdc_##Char_##__read_STATIC); \
py_bindstaticmethod(type, "write", stdc_##Char_##__write_STATIC); \
py_bindstaticmethod(type, "array", stdc_##Char_##__array_STATIC); \
py_newint(py_emplacedict(py_tpobject(type), py_name("size")), sizeof(char_)); \
}
DEF_BUILTIN_MEMORY_T(Char, char, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(UChar, unsigned char, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(Short, short, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(UShort, unsigned short, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(Int, int, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(UInt, unsigned int, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(Long, long, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(ULong, unsigned long, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(LongLong, long long, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(ULongLong, unsigned long long, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(Float, float, tp_float, py_newfloat, py_tofloat, float)
DEF_BUILTIN_MEMORY_T(Double, double, tp_float, py_newfloat, py_tofloat, double)
DEF_BUILTIN_MEMORY_T(Pointer, void*, tp_int, py_newint, py_toint, py_i64)
DEF_BUILTIN_MEMORY_T(Bool, bool, tp_bool, py_newbool, py_tobool, bool)
#undef DEF_BUILTIN_MEMORY_T
static bool stdc_malloc(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
py_i64 size = py_toint(&argv[0]);
void* p = py_malloc(size);
py_newint(py_retval(), (py_i64)(intptr_t)p);
return true;
}
static bool stdc_free(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
void* p = (void*)(intptr_t)py_toint(&argv[0]);
py_free(p);
py_newnone(py_retval());
return true;
}
static bool stdc_memcpy(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
void* dst = (void*)(intptr_t)py_toint(&argv[0]);
void* src = (void*)(intptr_t)py_toint(&argv[1]);
py_i64 n = py_toint(&argv[2]);
memcpy(dst, src, (size_t)n);
py_newnone(py_retval());
return true;
}
static bool stdc_memset(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
void* dst = (void*)(intptr_t)py_toint(&argv[0]);
int value = (int)py_toint(&argv[1]);
py_i64 n = py_toint(&argv[2]);
memset(dst, value, (size_t)n);
py_newnone(py_retval());
return true;
}
static bool stdc_memcmp(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
void* p1 = (void*)(intptr_t)py_toint(&argv[0]);
void* p2 = (void*)(intptr_t)py_toint(&argv[1]);
py_i64 n = py_toint(&argv[2]);
int res = memcmp(p1, p2, (size_t)n);
py_newint(py_retval(), (py_i64)res);
return true;
}
static bool stdc_addressof(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(!py_checkinstance(argv, tp_stdc_Memory)) return false;
void* ud = py_touserdata(argv);
py_newint(py_retval(), (py_i64)(intptr_t)ud);
return true;
}
static bool stdc_sizeof(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_type);
py_Type type = py_totype(&argv[0]);
if(!py_issubclass(type, tp_stdc_Memory)) {
return TypeError("expected a type derived from stdc.Memory");
}
py_assign(py_retval(), py_getdict(py_tpobject(type), py_name("size")));
return true;
}
static bool stdc_read_cstr(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int);
char* p = (char*)(intptr_t)py_toint(&argv[0]);
py_newstr(py_retval(), p);
return true;
}
static bool stdc_write_cstr(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_str);
char* p = (char*)(intptr_t)py_toint(&argv[0]);
c11_sv sv = py_tosv(&argv[1]);
memcpy(p, sv.data, sv.size);
p[sv.size] = '\0';
py_newnone(py_retval());
return true;
}
static bool stdc_read_bytes(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
unsigned char* p = (unsigned char*)(intptr_t)py_toint(&argv[0]);
int size = py_toint(&argv[1]);
unsigned char* dst = py_newbytes(py_retval(), size);
memcpy(dst, p, size);
return true;
}
static bool stdc_write_bytes(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_bytes);
unsigned char* p = (unsigned char*)(intptr_t)py_toint(&argv[0]);
int size;
unsigned char* src = py_tobytes(&argv[1], &size);
memcpy(p, src, size);
py_newnone(py_retval());
return true;
}
void pk__add_module_stdc() {
py_Ref mod = py_newmodule("stdc");
py_bindfunc(mod, "malloc", stdc_malloc);
py_bindfunc(mod, "free", stdc_free);
py_bindfunc(mod, "memcpy", stdc_memcpy);
py_bindfunc(mod, "memset", stdc_memset);
py_bindfunc(mod, "memcmp", stdc_memcmp);
py_bindfunc(mod, "addressof", stdc_addressof);
py_bindfunc(mod, "sizeof", stdc_sizeof);
py_bindfunc(mod, "read_cstr", stdc_read_cstr);
py_bindfunc(mod, "write_cstr", stdc_write_cstr);
py_bindfunc(mod, "read_bytes", stdc_read_bytes);
py_bindfunc(mod, "write_bytes", stdc_write_bytes);
py_Type Memory = py_newtype("Memory", tp_object, mod, NULL);
assert(Memory == tp_stdc_Memory);
pk__bind_stdc_Char(mod);
pk__bind_stdc_UChar(mod);
pk__bind_stdc_Short(mod);
pk__bind_stdc_UShort(mod);
pk__bind_stdc_Int(mod);
pk__bind_stdc_UInt(mod);
pk__bind_stdc_Long(mod);
pk__bind_stdc_ULong(mod);
pk__bind_stdc_LongLong(mod);
pk__bind_stdc_ULongLong(mod);
for(int size = 1; size <= 8; size *= 2) {
for(py_Type t = tp_stdc_Char; t <= tp_stdc_ULongLong; t += 2) {
py_Ref size_var = py_getdict(py_tpobject(t), py_name("size"));
if(py_toint(size_var) == size) {
char buf[16];
snprintf(buf, sizeof(buf), "Int%d", size * 8);
py_setdict(mod, py_name(buf), py_tpobject(t));
snprintf(buf, sizeof(buf), "UInt%d", size * 8);
py_setdict(mod, py_name(buf), py_tpobject(t + 1));
break;
}
}
}
for(py_Type t = tp_stdc_Char; t <= tp_stdc_ULongLong; t += 2) {
py_Ref size_var = py_getdict(py_tpobject(t), py_name("size"));
if(py_toint(size_var) == sizeof(size_t)) {
py_setdict(mod, py_name("SizeT"), py_tpobject(t + 1));
break;
}
}
if(sizeof(void*) == 4) {
py_setdict(mod, py_name("IntPtrT"), py_getdict(mod, py_name("Int32")));
py_setdict(mod, py_name("UIntPtrT"), py_getdict(mod, py_name("UInt32")));
} else if(sizeof(void*) == 8) {
py_setdict(mod, py_name("IntPtrT"), py_getdict(mod, py_name("Int64")));
py_setdict(mod, py_name("UIntPtrT"), py_getdict(mod, py_name("UInt64")));
} else {
c11__abort("unsupported pointer size");
}
pk__bind_stdc_Float(mod);
pk__bind_stdc_Double(mod);
pk__bind_stdc_Pointer(mod);
pk__bind_stdc_Bool(mod);
}
// src/modules\time.c
#define _XOPEN_SOURCE 700
#include <time.h>
#undef _XOPEN_SOURCE
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <profileapi.h>
#undef WIN32_LEAN_AND_MEAN
#endif
#include <assert.h>
#define NANOS_PER_SEC 1000000000
#ifndef __circle__
int64_t time_ns() {
#ifdef _WIN32
FILETIME system_time;
ULARGE_INTEGER large;
GetSystemTimePreciseAsFileTime(&system_time);
large.u.LowPart = system_time.dwLowDateTime;
large.u.HighPart = system_time.dwHighDateTime;
/* 11,644,473,600,000,000,000: number of nanoseconds between
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
days). */
return (large.QuadPart - 116444736000000000) * 100;
#else
struct timespec tms;
#ifdef CLOCK_REALTIME
clock_gettime(CLOCK_REALTIME, &tms);
#else
/* The C11 way */
timespec_get(&tms, TIME_UTC);
#endif
/* seconds, multiplied with 1 billion */
int64_t nanos = tms.tv_sec * (int64_t)NANOS_PER_SEC;
/* Add full nanoseconds */
nanos += tms.tv_nsec;
return nanos;
#endif
}
int64_t time_monotonic_ns() {
#ifdef _WIN32
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
LONGLONG ticksll = now.QuadPart;
static LARGE_INTEGER freq;
if(freq.QuadPart == 0) QueryPerformanceFrequency(&freq);
/* Convert ticks to nanoseconds */
return (ticksll * NANOS_PER_SEC) / freq.QuadPart;
#else
struct timespec tms;
#ifdef CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &tms);
#else
/* The C11 way */
timespec_get(&tms, TIME_UTC);
#endif
/* seconds, multiplied with 1 billion */
int64_t nanos = tms.tv_sec * (int64_t)NANOS_PER_SEC;
/* Add full nanoseconds */
nanos += tms.tv_nsec;
return nanos;
#endif
}
#else
int64_t time_ns() { return 0; }
int64_t time_monotonic_ns() { return 0; }
#endif
static bool time_time(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int64_t nanos = time_ns();
py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC);
return true;
}
static bool time_time_ns(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int64_t nanos = time_ns();
py_newint(py_retval(), nanos);
return true;
}
static bool time_time_monotonic(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int64_t nanos = time_monotonic_ns();
py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC);
return true;
}
static bool time_time_monotonic_ns(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
int64_t nanos = time_monotonic_ns();
py_newint(py_retval(), nanos);
return true;
}
static bool time_perf_counter(int argc, py_Ref argv) {
return time_time_monotonic(argc, argv);
}
static bool time_process_time(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_newfloat(py_retval(), (double)clock() / CLOCKS_PER_SEC);
return true;
}
static bool time_sleep(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_f64 secs;
if(!py_castfloat(argv, &secs)) return false;
int64_t start = time_monotonic_ns();
const int64_t end = start + secs * NANOS_PER_SEC;
while(true) {
int64_t now = time_monotonic_ns();
if(now >= end) break;
#if PK_ENABLE_THREADS
c11_thrd__yield();
#endif
}
py_newnone(py_retval());
return true;
}
static bool time_localtime(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_Type tp_struct_time = py_gettype("time", py_name("struct_time"));
assert(tp_struct_time);
struct tm* ud = py_newobject(py_retval(), tp_struct_time, 0, sizeof(struct tm));
time_t t = time(NULL);
*ud = *localtime(&t);
return true;
}
#define DEF_STRUCT_TIME__PROPERTY(name, expr) \
static bool struct_time__##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
struct tm* tm = py_touserdata(argv); \
py_newint(py_retval(), expr); \
return true; \
}
DEF_STRUCT_TIME__PROPERTY(tm_year, tm->tm_year + 1900)
DEF_STRUCT_TIME__PROPERTY(tm_mon, tm->tm_mon + 1)
DEF_STRUCT_TIME__PROPERTY(tm_mday, tm->tm_mday)
DEF_STRUCT_TIME__PROPERTY(tm_hour, tm->tm_hour)
DEF_STRUCT_TIME__PROPERTY(tm_min, tm->tm_min)
DEF_STRUCT_TIME__PROPERTY(tm_sec, tm->tm_sec)
DEF_STRUCT_TIME__PROPERTY(tm_wday, (tm->tm_wday + 6) % 7)
DEF_STRUCT_TIME__PROPERTY(tm_yday, tm->tm_yday + 1)
DEF_STRUCT_TIME__PROPERTY(tm_isdst, tm->tm_isdst)
#undef DEF_STRUCT_TIME__PROPERTY
void pk__add_module_time() {
py_Ref mod = py_newmodule("time");
py_Type tp_struct_time = py_newtype("struct_time", tp_object, mod, NULL);
py_bindproperty(tp_struct_time, "tm_year", struct_time__tm_year, NULL);
py_bindproperty(tp_struct_time, "tm_mon", struct_time__tm_mon, NULL);
py_bindproperty(tp_struct_time, "tm_mday", struct_time__tm_mday, NULL);
py_bindproperty(tp_struct_time, "tm_hour", struct_time__tm_hour, NULL);
py_bindproperty(tp_struct_time, "tm_min", struct_time__tm_min, NULL);
py_bindproperty(tp_struct_time, "tm_sec", struct_time__tm_sec, NULL);
py_bindproperty(tp_struct_time, "tm_wday", struct_time__tm_wday, NULL);
py_bindproperty(tp_struct_time, "tm_yday", struct_time__tm_yday, NULL);
py_bindproperty(tp_struct_time, "tm_isdst", struct_time__tm_isdst, NULL);
py_bindfunc(mod, "time", time_time);
py_bindfunc(mod, "time_ns", time_time_ns);
py_bindfunc(mod, "monotonic", time_time_monotonic);
py_bindfunc(mod, "monotonic_ns", time_time_monotonic_ns);
py_bindfunc(mod, "perf_counter", time_perf_counter);
py_bindfunc(mod, "process_time", time_process_time);
py_bindfunc(mod, "sleep", time_sleep);
py_bindfunc(mod, "localtime", time_localtime);
}
#undef NANOS_PER_SEC
#undef DEF_STRUCT_TIME__PROPERTY
// src/modules\traceback.c
static bool traceback_format_exc(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
VM* vm = pk_current_vm;
if(vm->top_frame) {
FrameExcInfo* info = Frame__top_exc_info(vm->top_frame);
if(info && !py_isnil(&info->exc)) {
char* res = formatexc_internal(&info->exc);
py_newstr(py_retval(), res);
PK_FREE(res);
return true;
}
}
py_newnone(py_retval());
return true;
}
static bool traceback_print_exc(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
py_printexc();
py_newnone(py_retval());
return true;
}
void pk__add_module_traceback() {
py_Ref mod = py_newmodule("traceback");
py_bindfunc(mod, "format_exc", traceback_format_exc);
py_bindfunc(mod, "print_exc", traceback_print_exc);
}
// src/modules\unicodedata.c
// clang-format off
const static c11_u32_range kEastAsianWidthRanges[] = {
{ 32, 126, "Na\0" },
{ 161, 161, "A\0" },
{ 162, 163, "Na\0" },
{ 164, 164, "A\0" },
{ 165, 166, "Na\0" },
{ 167, 168, "A\0" },
{ 170, 170, "A\0" },
{ 172, 172, "Na\0" },
{ 173, 174, "A\0" },
{ 175, 175, "Na\0" },
{ 176, 180, "A\0" },
{ 182, 186, "A\0" },
{ 188, 191, "A\0" },
{ 198, 198, "A\0" },
{ 208, 208, "A\0" },
{ 215, 216, "A\0" },
{ 222, 225, "A\0" },
{ 230, 230, "A\0" },
{ 232, 234, "A\0" },
{ 236, 237, "A\0" },
{ 240, 240, "A\0" },
{ 242, 243, "A\0" },
{ 247, 250, "A\0" },
{ 252, 252, "A\0" },
{ 254, 254, "A\0" },
{ 257, 257, "A\0" },
{ 273, 273, "A\0" },
{ 275, 275, "A\0" },
{ 283, 283, "A\0" },
{ 294, 295, "A\0" },
{ 299, 299, "A\0" },
{ 305, 307, "A\0" },
{ 312, 312, "A\0" },
{ 319, 322, "A\0" },
{ 324, 324, "A\0" },
{ 328, 331, "A\0" },
{ 333, 333, "A\0" },
{ 338, 339, "A\0" },
{ 358, 359, "A\0" },
{ 363, 363, "A\0" },
{ 462, 462, "A\0" },
{ 464, 464, "A\0" },
{ 466, 466, "A\0" },
{ 468, 468, "A\0" },
{ 470, 470, "A\0" },
{ 472, 472, "A\0" },
{ 474, 474, "A\0" },
{ 476, 476, "A\0" },
{ 593, 593, "A\0" },
{ 609, 609, "A\0" },
{ 708, 708, "A\0" },
{ 711, 711, "A\0" },
{ 713, 715, "A\0" },
{ 717, 717, "A\0" },
{ 720, 720, "A\0" },
{ 728, 731, "A\0" },
{ 733, 733, "A\0" },
{ 735, 735, "A\0" },
{ 768, 879, "A\0" },
{ 888, 889, "F\0" },
{ 896, 899, "F\0" },
{ 907, 907, "F\0" },
{ 909, 909, "F\0" },
{ 913, 929, "A\0" },
{ 930, 930, "F\0" },
{ 931, 937, "A\0" },
{ 945, 961, "A\0" },
{ 963, 969, "A\0" },
{ 1025, 1025, "A\0" },
{ 1040, 1103, "A\0" },
{ 1105, 1105, "A\0" },
{ 1328, 1328, "F\0" },
{ 1367, 1368, "F\0" },
{ 1419, 1420, "F\0" },
{ 1424, 1424, "F\0" },
{ 1480, 1487, "F\0" },
{ 1515, 1518, "F\0" },
{ 1525, 1535, "F\0" },
{ 1806, 1806, "F\0" },
{ 1867, 1868, "F\0" },
{ 1970, 1983, "F\0" },
{ 2043, 2044, "F\0" },
{ 2094, 2095, "F\0" },
{ 2111, 2111, "F\0" },
{ 2140, 2141, "F\0" },
{ 2143, 2143, "F\0" },
{ 2155, 2159, "F\0" },
{ 2191, 2191, "F\0" },
{ 2194, 2199, "F\0" },
{ 2436, 2436, "F\0" },
{ 2445, 2446, "F\0" },
{ 2449, 2450, "F\0" },
{ 2473, 2473, "F\0" },
{ 2481, 2481, "F\0" },
{ 2483, 2485, "F\0" },
{ 2490, 2491, "F\0" },
{ 2501, 2502, "F\0" },
{ 2505, 2506, "F\0" },
{ 2511, 2518, "F\0" },
{ 2520, 2523, "F\0" },
{ 2526, 2526, "F\0" },
{ 2532, 2533, "F\0" },
{ 2559, 2560, "F\0" },
{ 2564, 2564, "F\0" },
{ 2571, 2574, "F\0" },
{ 2577, 2578, "F\0" },
{ 2601, 2601, "F\0" },
{ 2609, 2609, "F\0" },
{ 2612, 2612, "F\0" },
{ 2615, 2615, "F\0" },
{ 2618, 2619, "F\0" },
{ 2621, 2621, "F\0" },
{ 2627, 2630, "F\0" },
{ 2633, 2634, "F\0" },
{ 2638, 2640, "F\0" },
{ 2642, 2648, "F\0" },
{ 2653, 2653, "F\0" },
{ 2655, 2661, "F\0" },
{ 2679, 2688, "F\0" },
{ 2692, 2692, "F\0" },
{ 2702, 2702, "F\0" },
{ 2706, 2706, "F\0" },
{ 2729, 2729, "F\0" },
{ 2737, 2737, "F\0" },
{ 2740, 2740, "F\0" },
{ 2746, 2747, "F\0" },
{ 2758, 2758, "F\0" },
{ 2762, 2762, "F\0" },
{ 2766, 2767, "F\0" },
{ 2769, 2783, "F\0" },
{ 2788, 2789, "F\0" },
{ 2802, 2808, "F\0" },
{ 2816, 2816, "F\0" },
{ 2820, 2820, "F\0" },
{ 2829, 2830, "F\0" },
{ 2833, 2834, "F\0" },
{ 2857, 2857, "F\0" },
{ 2865, 2865, "F\0" },
{ 2868, 2868, "F\0" },
{ 2874, 2875, "F\0" },
{ 2885, 2886, "F\0" },
{ 2889, 2890, "F\0" },
{ 2894, 2900, "F\0" },
{ 2904, 2907, "F\0" },
{ 2910, 2910, "F\0" },
{ 2916, 2917, "F\0" },
{ 2936, 2945, "F\0" },
{ 2948, 2948, "F\0" },
{ 2955, 2957, "F\0" },
{ 2961, 2961, "F\0" },
{ 2966, 2968, "F\0" },
{ 2971, 2971, "F\0" },
{ 2973, 2973, "F\0" },
{ 2976, 2978, "F\0" },
{ 2981, 2983, "F\0" },
{ 2987, 2989, "F\0" },
{ 3002, 3005, "F\0" },
{ 3011, 3013, "F\0" },
{ 3017, 3017, "F\0" },
{ 3022, 3023, "F\0" },
{ 3025, 3030, "F\0" },
{ 3032, 3045, "F\0" },
{ 3067, 3071, "F\0" },
{ 3085, 3085, "F\0" },
{ 3089, 3089, "F\0" },
{ 3113, 3113, "F\0" },
{ 3130, 3131, "F\0" },
{ 3141, 3141, "F\0" },
{ 3145, 3145, "F\0" },
{ 3150, 3156, "F\0" },
{ 3159, 3159, "F\0" },
{ 3163, 3164, "F\0" },
{ 3166, 3167, "F\0" },
{ 3172, 3173, "F\0" },
{ 3184, 3190, "F\0" },
{ 3213, 3213, "F\0" },
{ 3217, 3217, "F\0" },
{ 3241, 3241, "F\0" },
{ 3252, 3252, "F\0" },
{ 3258, 3259, "F\0" },
{ 3269, 3269, "F\0" },
{ 3273, 3273, "F\0" },
{ 3278, 3284, "F\0" },
{ 3287, 3292, "F\0" },
{ 3295, 3295, "F\0" },
{ 3300, 3301, "F\0" },
{ 3312, 3312, "F\0" },
{ 3315, 3327, "F\0" },
{ 3341, 3341, "F\0" },
{ 3345, 3345, "F\0" },
{ 3397, 3397, "F\0" },
{ 3401, 3401, "F\0" },
{ 3408, 3411, "F\0" },
{ 3428, 3429, "F\0" },
{ 3456, 3456, "F\0" },
{ 3460, 3460, "F\0" },
{ 3479, 3481, "F\0" },
{ 3506, 3506, "F\0" },
{ 3516, 3516, "F\0" },
{ 3518, 3519, "F\0" },
{ 3527, 3529, "F\0" },
{ 3531, 3534, "F\0" },
{ 3541, 3541, "F\0" },
{ 3543, 3543, "F\0" },
{ 3552, 3557, "F\0" },
{ 3568, 3569, "F\0" },
{ 3573, 3584, "F\0" },
{ 3643, 3646, "F\0" },
{ 3676, 3712, "F\0" },
{ 3715, 3715, "F\0" },
{ 3717, 3717, "F\0" },
{ 3723, 3723, "F\0" },
{ 3748, 3748, "F\0" },
{ 3750, 3750, "F\0" },
{ 3774, 3775, "F\0" },
{ 3781, 3781, "F\0" },
{ 3783, 3783, "F\0" },
{ 3790, 3791, "F\0" },
{ 3802, 3803, "F\0" },
{ 3808, 3839, "F\0" },
{ 3912, 3912, "F\0" },
{ 3949, 3952, "F\0" },
{ 3992, 3992, "F\0" },
{ 4029, 4029, "F\0" },
{ 4045, 4045, "F\0" },
{ 4059, 4095, "F\0" },
{ 4294, 4294, "F\0" },
{ 4296, 4300, "F\0" },
{ 4302, 4303, "F\0" },
{ 4352, 4447, "W\0" },
{ 4681, 4681, "F\0" },
{ 4686, 4687, "F\0" },
{ 4695, 4695, "F\0" },
{ 4697, 4697, "F\0" },
{ 4702, 4703, "F\0" },
{ 4745, 4745, "F\0" },
{ 4750, 4751, "F\0" },
{ 4785, 4785, "F\0" },
{ 4790, 4791, "F\0" },
{ 4799, 4799, "F\0" },
{ 4801, 4801, "F\0" },
{ 4806, 4807, "F\0" },
{ 4823, 4823, "F\0" },
{ 4881, 4881, "F\0" },
{ 4886, 4887, "F\0" },
{ 4955, 4956, "F\0" },
{ 4989, 4991, "F\0" },
{ 5018, 5023, "F\0" },
{ 5110, 5111, "F\0" },
{ 5118, 5119, "F\0" },
{ 5789, 5791, "F\0" },
{ 5881, 5887, "F\0" },
{ 5910, 5918, "F\0" },
{ 5943, 5951, "F\0" },
{ 5972, 5983, "F\0" },
{ 5997, 5997, "F\0" },
{ 6001, 6001, "F\0" },
{ 6004, 6015, "F\0" },
{ 6110, 6111, "F\0" },
{ 6122, 6127, "F\0" },
{ 6138, 6143, "F\0" },
{ 6170, 6175, "F\0" },
{ 6265, 6271, "F\0" },
{ 6315, 6319, "F\0" },
{ 6390, 6399, "F\0" },
{ 6431, 6431, "F\0" },
{ 6444, 6447, "F\0" },
{ 6460, 6463, "F\0" },
{ 6465, 6467, "F\0" },
{ 6510, 6511, "F\0" },
{ 6517, 6527, "F\0" },
{ 6572, 6575, "F\0" },
{ 6602, 6607, "F\0" },
{ 6619, 6621, "F\0" },
{ 6684, 6685, "F\0" },
{ 6751, 6751, "F\0" },
{ 6781, 6782, "F\0" },
{ 6794, 6799, "F\0" },
{ 6810, 6815, "F\0" },
{ 6830, 6831, "F\0" },
{ 6863, 6911, "F\0" },
{ 6989, 6991, "F\0" },
{ 7039, 7039, "F\0" },
{ 7156, 7163, "F\0" },
{ 7224, 7226, "F\0" },
{ 7242, 7244, "F\0" },
{ 7305, 7311, "F\0" },
{ 7355, 7356, "F\0" },
{ 7368, 7375, "F\0" },
{ 7419, 7423, "F\0" },
{ 7958, 7959, "F\0" },
{ 7966, 7967, "F\0" },
{ 8006, 8007, "F\0" },
{ 8014, 8015, "F\0" },
{ 8024, 8024, "F\0" },
{ 8026, 8026, "F\0" },
{ 8028, 8028, "F\0" },
{ 8030, 8030, "F\0" },
{ 8062, 8063, "F\0" },
{ 8117, 8117, "F\0" },
{ 8133, 8133, "F\0" },
{ 8148, 8149, "F\0" },
{ 8156, 8156, "F\0" },
{ 8176, 8177, "F\0" },
{ 8181, 8181, "F\0" },
{ 8191, 8191, "F\0" },
{ 8208, 8208, "A\0" },
{ 8211, 8214, "A\0" },
{ 8216, 8217, "A\0" },
{ 8220, 8221, "A\0" },
{ 8224, 8226, "A\0" },
{ 8228, 8231, "A\0" },
{ 8240, 8240, "A\0" },
{ 8242, 8243, "A\0" },
{ 8245, 8245, "A\0" },
{ 8251, 8251, "A\0" },
{ 8254, 8254, "A\0" },
{ 8293, 8293, "F\0" },
{ 8306, 8307, "F\0" },
{ 8308, 8308, "A\0" },
{ 8319, 8319, "A\0" },
{ 8321, 8324, "A\0" },
{ 8335, 8335, "F\0" },
{ 8349, 8351, "F\0" },
{ 8361, 8361, "H\0" },
{ 8364, 8364, "A\0" },
{ 8385, 8399, "F\0" },
{ 8433, 8447, "F\0" },
{ 8451, 8451, "A\0" },
{ 8453, 8453, "A\0" },
{ 8457, 8457, "A\0" },
{ 8467, 8467, "A\0" },
{ 8470, 8470, "A\0" },
{ 8481, 8482, "A\0" },
{ 8486, 8486, "A\0" },
{ 8491, 8491, "A\0" },
{ 8531, 8532, "A\0" },
{ 8539, 8542, "A\0" },
{ 8544, 8555, "A\0" },
{ 8560, 8569, "A\0" },
{ 8585, 8585, "A\0" },
{ 8588, 8591, "F\0" },
{ 8592, 8601, "A\0" },
{ 8632, 8633, "A\0" },
{ 8658, 8658, "A\0" },
{ 8660, 8660, "A\0" },
{ 8679, 8679, "A\0" },
{ 8704, 8704, "A\0" },
{ 8706, 8707, "A\0" },
{ 8711, 8712, "A\0" },
{ 8715, 8715, "A\0" },
{ 8719, 8719, "A\0" },
{ 8721, 8721, "A\0" },
{ 8725, 8725, "A\0" },
{ 8730, 8730, "A\0" },
{ 8733, 8736, "A\0" },
{ 8739, 8739, "A\0" },
{ 8741, 8741, "A\0" },
{ 8743, 8748, "A\0" },
{ 8750, 8750, "A\0" },
{ 8756, 8759, "A\0" },
{ 8764, 8765, "A\0" },
{ 8776, 8776, "A\0" },
{ 8780, 8780, "A\0" },
{ 8786, 8786, "A\0" },
{ 8800, 8801, "A\0" },
{ 8804, 8807, "A\0" },
{ 8810, 8811, "A\0" },
{ 8814, 8815, "A\0" },
{ 8834, 8835, "A\0" },
{ 8838, 8839, "A\0" },
{ 8853, 8853, "A\0" },
{ 8857, 8857, "A\0" },
{ 8869, 8869, "A\0" },
{ 8895, 8895, "A\0" },
{ 8978, 8978, "A\0" },
{ 8986, 8987, "W\0" },
{ 9001, 9002, "W\0" },
{ 9193, 9196, "W\0" },
{ 9200, 9200, "W\0" },
{ 9203, 9203, "W\0" },
{ 9255, 9279, "F\0" },
{ 9291, 9311, "F\0" },
{ 9312, 9449, "A\0" },
{ 9451, 9547, "A\0" },
{ 9552, 9587, "A\0" },
{ 9600, 9615, "A\0" },
{ 9618, 9621, "A\0" },
{ 9632, 9633, "A\0" },
{ 9635, 9641, "A\0" },
{ 9650, 9651, "A\0" },
{ 9654, 9655, "A\0" },
{ 9660, 9661, "A\0" },
{ 9664, 9665, "A\0" },
{ 9670, 9672, "A\0" },
{ 9675, 9675, "A\0" },
{ 9678, 9681, "A\0" },
{ 9698, 9701, "A\0" },
{ 9711, 9711, "A\0" },
{ 9725, 9726, "W\0" },
{ 9733, 9734, "A\0" },
{ 9737, 9737, "A\0" },
{ 9742, 9743, "A\0" },
{ 9748, 9749, "W\0" },
{ 9756, 9756, "A\0" },
{ 9758, 9758, "A\0" },
{ 9792, 9792, "A\0" },
{ 9794, 9794, "A\0" },
{ 9800, 9811, "W\0" },
{ 9824, 9825, "A\0" },
{ 9827, 9829, "A\0" },
{ 9831, 9834, "A\0" },
{ 9836, 9837, "A\0" },
{ 9839, 9839, "A\0" },
{ 9855, 9855, "W\0" },
{ 9875, 9875, "W\0" },
{ 9886, 9887, "A\0" },
{ 9889, 9889, "W\0" },
{ 9898, 9899, "W\0" },
{ 9917, 9918, "W\0" },
{ 9919, 9919, "A\0" },
{ 9924, 9925, "W\0" },
{ 9926, 9933, "A\0" },
{ 9934, 9934, "W\0" },
{ 9935, 9939, "A\0" },
{ 9940, 9940, "W\0" },
{ 9941, 9953, "A\0" },
{ 9955, 9955, "A\0" },
{ 9960, 9961, "A\0" },
{ 9962, 9962, "W\0" },
{ 9963, 9969, "A\0" },
{ 9970, 9971, "W\0" },
{ 9972, 9972, "A\0" },
{ 9973, 9973, "W\0" },
{ 9974, 9977, "A\0" },
{ 9978, 9978, "W\0" },
{ 9979, 9980, "A\0" },
{ 9981, 9981, "W\0" },
{ 9982, 9983, "A\0" },
{ 9989, 9989, "W\0" },
{ 9994, 9995, "W\0" },
{ 10024, 10024, "W\0" },
{ 10045, 10045, "A\0" },
{ 10060, 10060, "W\0" },
{ 10062, 10062, "W\0" },
{ 10067, 10069, "W\0" },
{ 10071, 10071, "W\0" },
{ 10102, 10111, "A\0" },
{ 10133, 10135, "W\0" },
{ 10160, 10160, "W\0" },
{ 10175, 10175, "W\0" },
{ 10214, 10221, "Na\0" },
{ 10629, 10630, "Na\0" },
{ 11035, 11036, "W\0" },
{ 11088, 11088, "W\0" },
{ 11093, 11093, "W\0" },
{ 11094, 11097, "A\0" },
{ 11124, 11125, "F\0" },
{ 11158, 11158, "F\0" },
{ 11508, 11512, "F\0" },
{ 11558, 11558, "F\0" },
{ 11560, 11564, "F\0" },
{ 11566, 11567, "F\0" },
{ 11624, 11630, "F\0" },
{ 11633, 11646, "F\0" },
{ 11671, 11679, "F\0" },
{ 11687, 11687, "F\0" },
{ 11695, 11695, "F\0" },
{ 11703, 11703, "F\0" },
{ 11711, 11711, "F\0" },
{ 11719, 11719, "F\0" },
{ 11727, 11727, "F\0" },
{ 11735, 11735, "F\0" },
{ 11743, 11743, "F\0" },
{ 11870, 11903, "F\0" },
{ 11904, 11929, "W\0" },
{ 11930, 11930, "F\0" },
{ 11931, 12019, "W\0" },
{ 12020, 12031, "F\0" },
{ 12032, 12245, "W\0" },
{ 12246, 12271, "F\0" },
{ 12272, 12283, "W\0" },
{ 12284, 12288, "F\0" },
{ 12289, 12350, "W\0" },
{ 12352, 12352, "F\0" },
{ 12353, 12438, "W\0" },
{ 12439, 12440, "F\0" },
{ 12441, 12543, "W\0" },
{ 12544, 12548, "F\0" },
{ 12549, 12591, "W\0" },
{ 12592, 12592, "F\0" },
{ 12593, 12686, "W\0" },
{ 12687, 12687, "F\0" },
{ 12688, 12771, "W\0" },
{ 12772, 12783, "F\0" },
{ 12784, 12830, "W\0" },
{ 12831, 12831, "F\0" },
{ 12832, 12871, "W\0" },
{ 12872, 12879, "A\0" },
{ 12880, 19903, "W\0" },
{ 19968, 42124, "W\0" },
{ 42125, 42127, "F\0" },
{ 42128, 42182, "W\0" },
{ 42183, 42191, "F\0" },
{ 42540, 42559, "F\0" },
{ 42744, 42751, "F\0" },
{ 42955, 42959, "F\0" },
{ 42962, 42962, "F\0" },
{ 42964, 42964, "F\0" },
{ 42970, 42993, "F\0" },
{ 43053, 43055, "F\0" },
{ 43066, 43071, "F\0" },
{ 43128, 43135, "F\0" },
{ 43206, 43213, "F\0" },
{ 43226, 43231, "F\0" },
{ 43348, 43358, "F\0" },
{ 43360, 43388, "W\0" },
{ 43389, 43391, "F\0" },
{ 43470, 43470, "F\0" },
{ 43482, 43485, "F\0" },
{ 43519, 43519, "F\0" },
{ 43575, 43583, "F\0" },
{ 43598, 43599, "F\0" },
{ 43610, 43611, "F\0" },
{ 43715, 43738, "F\0" },
{ 43767, 43776, "F\0" },
{ 43783, 43784, "F\0" },
{ 43791, 43792, "F\0" },
{ 43799, 43807, "F\0" },
{ 43815, 43815, "F\0" },
{ 43823, 43823, "F\0" },
{ 43884, 43887, "F\0" },
{ 44014, 44015, "F\0" },
{ 44026, 44031, "F\0" },
{ 44032, 55203, "W\0" },
{ 55204, 55215, "F\0" },
{ 55239, 55242, "F\0" },
{ 55292, 55295, "F\0" },
{ 57344, 63743, "A\0" },
{ 63744, 64109, "W\0" },
{ 64110, 64111, "F\0" },
{ 64112, 64217, "W\0" },
{ 64218, 64255, "F\0" },
{ 64263, 64274, "F\0" },
{ 64280, 64284, "F\0" },
{ 64311, 64311, "F\0" },
{ 64317, 64317, "F\0" },
{ 64319, 64319, "F\0" },
{ 64322, 64322, "F\0" },
{ 64325, 64325, "F\0" },
{ 64451, 64466, "F\0" },
{ 64912, 64913, "F\0" },
{ 64968, 64974, "F\0" },
{ 64976, 65007, "F\0" },
{ 65024, 65039, "A\0" },
{ 65040, 65049, "W\0" },
{ 65050, 65055, "F\0" },
{ 65072, 65106, "W\0" },
{ 65107, 65107, "F\0" },
{ 65108, 65126, "W\0" },
{ 65127, 65127, "F\0" },
{ 65128, 65131, "W\0" },
{ 65132, 65135, "F\0" },
{ 65141, 65141, "F\0" },
{ 65277, 65278, "F\0" },
{ 65280, 65376, "F\0" },
{ 65377, 65470, "H\0" },
{ 65471, 65473, "F\0" },
{ 65474, 65479, "H\0" },
{ 65480, 65481, "F\0" },
{ 65482, 65487, "H\0" },
{ 65488, 65489, "F\0" },
{ 65490, 65495, "H\0" },
{ 65496, 65497, "F\0" },
{ 65498, 65500, "H\0" },
{ 65501, 65511, "F\0" },
{ 65512, 65518, "H\0" },
{ 65519, 65528, "F\0" },
{ 65533, 65533, "A\0" },
{ 65534, 65535, "F\0" },
{ 65548, 65548, "F\0" },
{ 65575, 65575, "F\0" },
{ 65595, 65595, "F\0" },
{ 65598, 65598, "F\0" },
{ 65614, 65615, "F\0" },
{ 65630, 65663, "F\0" },
{ 65787, 65791, "F\0" },
{ 65795, 65798, "F\0" },
{ 65844, 65846, "F\0" },
{ 65935, 65935, "F\0" },
{ 65949, 65951, "F\0" },
{ 65953, 65999, "F\0" },
{ 66046, 66175, "F\0" },
{ 66205, 66207, "F\0" },
{ 66257, 66271, "F\0" },
{ 66300, 66303, "F\0" },
{ 66340, 66348, "F\0" },
{ 66379, 66383, "F\0" },
{ 66427, 66431, "F\0" },
{ 66462, 66462, "F\0" },
{ 66500, 66503, "F\0" },
{ 66518, 66559, "F\0" },
{ 66718, 66719, "F\0" },
{ 66730, 66735, "F\0" },
{ 66772, 66775, "F\0" },
{ 66812, 66815, "F\0" },
{ 66856, 66863, "F\0" },
{ 66916, 66926, "F\0" },
{ 66939, 66939, "F\0" },
{ 66955, 66955, "F\0" },
{ 66963, 66963, "F\0" },
{ 66966, 66966, "F\0" },
{ 66978, 66978, "F\0" },
{ 66994, 66994, "F\0" },
{ 67002, 67002, "F\0" },
{ 67005, 67071, "F\0" },
{ 67383, 67391, "F\0" },
{ 67414, 67423, "F\0" },
{ 67432, 67455, "F\0" },
{ 67462, 67462, "F\0" },
{ 67505, 67505, "F\0" },
{ 67515, 67583, "F\0" },
{ 67590, 67591, "F\0" },
{ 67593, 67593, "F\0" },
{ 67638, 67638, "F\0" },
{ 67641, 67643, "F\0" },
{ 67645, 67646, "F\0" },
{ 67670, 67670, "F\0" },
{ 67743, 67750, "F\0" },
{ 67760, 67807, "F\0" },
{ 67827, 67827, "F\0" },
{ 67830, 67834, "F\0" },
{ 67868, 67870, "F\0" },
{ 67898, 67902, "F\0" },
{ 67904, 67967, "F\0" },
{ 68024, 68027, "F\0" },
{ 68048, 68049, "F\0" },
{ 68100, 68100, "F\0" },
{ 68103, 68107, "F\0" },
{ 68116, 68116, "F\0" },
{ 68120, 68120, "F\0" },
{ 68150, 68151, "F\0" },
{ 68155, 68158, "F\0" },
{ 68169, 68175, "F\0" },
{ 68185, 68191, "F\0" },
{ 68256, 68287, "F\0" },
{ 68327, 68330, "F\0" },
{ 68343, 68351, "F\0" },
{ 68406, 68408, "F\0" },
{ 68438, 68439, "F\0" },
{ 68467, 68471, "F\0" },
{ 68498, 68504, "F\0" },
{ 68509, 68520, "F\0" },
{ 68528, 68607, "F\0" },
{ 68681, 68735, "F\0" },
{ 68787, 68799, "F\0" },
{ 68851, 68857, "F\0" },
{ 68904, 68911, "F\0" },
{ 68922, 69215, "F\0" },
{ 69247, 69247, "F\0" },
{ 69290, 69290, "F\0" },
{ 69294, 69295, "F\0" },
{ 69298, 69375, "F\0" },
{ 69416, 69423, "F\0" },
{ 69466, 69487, "F\0" },
{ 69514, 69551, "F\0" },
{ 69580, 69599, "F\0" },
{ 69623, 69631, "F\0" },
{ 69710, 69713, "F\0" },
{ 69750, 69758, "F\0" },
{ 69827, 69836, "F\0" },
{ 69838, 69839, "F\0" },
{ 69865, 69871, "F\0" },
{ 69882, 69887, "F\0" },
{ 69941, 69941, "F\0" },
{ 69960, 69967, "F\0" },
{ 70007, 70015, "F\0" },
{ 70112, 70112, "F\0" },
{ 70133, 70143, "F\0" },
{ 70162, 70162, "F\0" },
{ 70207, 70271, "F\0" },
{ 70279, 70279, "F\0" },
{ 70281, 70281, "F\0" },
{ 70286, 70286, "F\0" },
{ 70302, 70302, "F\0" },
{ 70314, 70319, "F\0" },
{ 70379, 70383, "F\0" },
{ 70394, 70399, "F\0" },
{ 70404, 70404, "F\0" },
{ 70413, 70414, "F\0" },
{ 70417, 70418, "F\0" },
{ 70441, 70441, "F\0" },
{ 70449, 70449, "F\0" },
{ 70452, 70452, "F\0" },
{ 70458, 70458, "F\0" },
{ 70469, 70470, "F\0" },
{ 70473, 70474, "F\0" },
{ 70478, 70479, "F\0" },
{ 70481, 70486, "F\0" },
{ 70488, 70492, "F\0" },
{ 70500, 70501, "F\0" },
{ 70509, 70511, "F\0" },
{ 70517, 70655, "F\0" },
{ 70748, 70748, "F\0" },
{ 70754, 70783, "F\0" },
{ 70856, 70863, "F\0" },
{ 70874, 71039, "F\0" },
{ 71094, 71095, "F\0" },
{ 71134, 71167, "F\0" },
{ 71237, 71247, "F\0" },
{ 71258, 71263, "F\0" },
{ 71277, 71295, "F\0" },
{ 71354, 71359, "F\0" },
{ 71370, 71423, "F\0" },
{ 71451, 71452, "F\0" },
{ 71468, 71471, "F\0" },
{ 71495, 71679, "F\0" },
{ 71740, 71839, "F\0" },
{ 71923, 71934, "F\0" },
{ 71943, 71944, "F\0" },
{ 71946, 71947, "F\0" },
{ 71956, 71956, "F\0" },
{ 71959, 71959, "F\0" },
{ 71990, 71990, "F\0" },
{ 71993, 71994, "F\0" },
{ 72007, 72015, "F\0" },
{ 72026, 72095, "F\0" },
{ 72104, 72105, "F\0" },
{ 72152, 72153, "F\0" },
{ 72165, 72191, "F\0" },
{ 72264, 72271, "F\0" },
{ 72355, 72367, "F\0" },
{ 72441, 72703, "F\0" },
{ 72713, 72713, "F\0" },
{ 72759, 72759, "F\0" },
{ 72774, 72783, "F\0" },
{ 72813, 72815, "F\0" },
{ 72848, 72849, "F\0" },
{ 72872, 72872, "F\0" },
{ 72887, 72959, "F\0" },
{ 72967, 72967, "F\0" },
{ 72970, 72970, "F\0" },
{ 73015, 73017, "F\0" },
{ 73019, 73019, "F\0" },
{ 73022, 73022, "F\0" },
{ 73032, 73039, "F\0" },
{ 73050, 73055, "F\0" },
{ 73062, 73062, "F\0" },
{ 73065, 73065, "F\0" },
{ 73103, 73103, "F\0" },
{ 73106, 73106, "F\0" },
{ 73113, 73119, "F\0" },
{ 73130, 73439, "F\0" },
{ 73465, 73647, "F\0" },
{ 73649, 73663, "F\0" },
{ 73714, 73726, "F\0" },
{ 74650, 74751, "F\0" },
{ 74863, 74863, "F\0" },
{ 74869, 74879, "F\0" },
{ 75076, 77711, "F\0" },
{ 77811, 77823, "F\0" },
{ 78895, 78895, "F\0" },
{ 78905, 82943, "F\0" },
{ 83527, 92159, "F\0" },
{ 92729, 92735, "F\0" },
{ 92767, 92767, "F\0" },
{ 92778, 92781, "F\0" },
{ 92863, 92863, "F\0" },
{ 92874, 92879, "F\0" },
{ 92910, 92911, "F\0" },
{ 92918, 92927, "F\0" },
{ 92998, 93007, "F\0" },
{ 93018, 93018, "F\0" },
{ 93026, 93026, "F\0" },
{ 93048, 93052, "F\0" },
{ 93072, 93759, "F\0" },
{ 93851, 93951, "F\0" },
{ 94027, 94030, "F\0" },
{ 94088, 94094, "F\0" },
{ 94112, 94175, "F\0" },
{ 94176, 94180, "W\0" },
{ 94181, 94191, "F\0" },
{ 94192, 94193, "W\0" },
{ 94194, 94207, "F\0" },
{ 94208, 100343, "W\0" },
{ 100344, 100351, "F\0" },
{ 100352, 101589, "W\0" },
{ 101590, 101631, "F\0" },
{ 101632, 101640, "W\0" },
{ 101641, 110575, "F\0" },
{ 110576, 110579, "W\0" },
{ 110580, 110580, "F\0" },
{ 110581, 110587, "W\0" },
{ 110588, 110588, "F\0" },
{ 110589, 110590, "W\0" },
{ 110591, 110591, "F\0" },
{ 110592, 110882, "W\0" },
{ 110883, 110927, "F\0" },
{ 110928, 110930, "W\0" },
{ 110931, 110947, "F\0" },
{ 110948, 110951, "W\0" },
{ 110952, 110959, "F\0" },
{ 110960, 111355, "W\0" },
{ 111356, 113663, "F\0" },
{ 113771, 113775, "F\0" },
{ 113789, 113791, "F\0" },
{ 113801, 113807, "F\0" },
{ 113818, 113819, "F\0" },
{ 113828, 118527, "F\0" },
{ 118574, 118575, "F\0" },
{ 118599, 118607, "F\0" },
{ 118724, 118783, "F\0" },
{ 119030, 119039, "F\0" },
{ 119079, 119080, "F\0" },
{ 119275, 119295, "F\0" },
{ 119366, 119519, "F\0" },
{ 119540, 119551, "F\0" },
{ 119639, 119647, "F\0" },
{ 119673, 119807, "F\0" },
{ 119893, 119893, "F\0" },
{ 119965, 119965, "F\0" },
{ 119968, 119969, "F\0" },
{ 119971, 119972, "F\0" },
{ 119975, 119976, "F\0" },
{ 119981, 119981, "F\0" },
{ 119994, 119994, "F\0" },
{ 119996, 119996, "F\0" },
{ 120004, 120004, "F\0" },
{ 120070, 120070, "F\0" },
{ 120075, 120076, "F\0" },
{ 120085, 120085, "F\0" },
{ 120093, 120093, "F\0" },
{ 120122, 120122, "F\0" },
{ 120127, 120127, "F\0" },
{ 120133, 120133, "F\0" },
{ 120135, 120137, "F\0" },
{ 120145, 120145, "F\0" },
{ 120486, 120487, "F\0" },
{ 120780, 120781, "F\0" },
{ 121484, 121498, "F\0" },
{ 121504, 121504, "F\0" },
{ 121520, 122623, "F\0" },
{ 122655, 122879, "F\0" },
{ 122887, 122887, "F\0" },
{ 122905, 122906, "F\0" },
{ 122914, 122914, "F\0" },
{ 122917, 122917, "F\0" },
{ 122923, 123135, "F\0" },
{ 123181, 123183, "F\0" },
{ 123198, 123199, "F\0" },
{ 123210, 123213, "F\0" },
{ 123216, 123535, "F\0" },
{ 123567, 123583, "F\0" },
{ 123642, 123646, "F\0" },
{ 123648, 124895, "F\0" },
{ 124903, 124903, "F\0" },
{ 124908, 124908, "F\0" },
{ 124911, 124911, "F\0" },
{ 124927, 124927, "F\0" },
{ 125125, 125126, "F\0" },
{ 125143, 125183, "F\0" },
{ 125260, 125263, "F\0" },
{ 125274, 125277, "F\0" },
{ 125280, 126064, "F\0" },
{ 126133, 126208, "F\0" },
{ 126270, 126463, "F\0" },
{ 126468, 126468, "F\0" },
{ 126496, 126496, "F\0" },
{ 126499, 126499, "F\0" },
{ 126501, 126502, "F\0" },
{ 126504, 126504, "F\0" },
{ 126515, 126515, "F\0" },
{ 126520, 126520, "F\0" },
{ 126522, 126522, "F\0" },
{ 126524, 126529, "F\0" },
{ 126531, 126534, "F\0" },
{ 126536, 126536, "F\0" },
{ 126538, 126538, "F\0" },
{ 126540, 126540, "F\0" },
{ 126544, 126544, "F\0" },
{ 126547, 126547, "F\0" },
{ 126549, 126550, "F\0" },
{ 126552, 126552, "F\0" },
{ 126554, 126554, "F\0" },
{ 126556, 126556, "F\0" },
{ 126558, 126558, "F\0" },
{ 126560, 126560, "F\0" },
{ 126563, 126563, "F\0" },
{ 126565, 126566, "F\0" },
{ 126571, 126571, "F\0" },
{ 126579, 126579, "F\0" },
{ 126584, 126584, "F\0" },
{ 126589, 126589, "F\0" },
{ 126591, 126591, "F\0" },
{ 126602, 126602, "F\0" },
{ 126620, 126624, "F\0" },
{ 126628, 126628, "F\0" },
{ 126634, 126634, "F\0" },
{ 126652, 126703, "F\0" },
{ 126706, 126975, "F\0" },
{ 126980, 126980, "W\0" },
{ 127020, 127023, "F\0" },
{ 127124, 127135, "F\0" },
{ 127151, 127152, "F\0" },
{ 127168, 127168, "F\0" },
{ 127183, 127183, "W\0" },
{ 127184, 127184, "F\0" },
{ 127222, 127231, "F\0" },
{ 127232, 127242, "A\0" },
{ 127248, 127277, "A\0" },
{ 127280, 127337, "A\0" },
{ 127344, 127373, "A\0" },
{ 127374, 127374, "W\0" },
{ 127375, 127376, "A\0" },
{ 127377, 127386, "W\0" },
{ 127387, 127404, "A\0" },
{ 127406, 127461, "F\0" },
{ 127488, 127490, "W\0" },
{ 127491, 127503, "F\0" },
{ 127504, 127547, "W\0" },
{ 127548, 127551, "F\0" },
{ 127552, 127560, "W\0" },
{ 127561, 127567, "F\0" },
{ 127568, 127569, "W\0" },
{ 127570, 127583, "F\0" },
{ 127584, 127589, "W\0" },
{ 127590, 127743, "F\0" },
{ 127744, 127776, "W\0" },
{ 127789, 127797, "W\0" },
{ 127799, 127868, "W\0" },
{ 127870, 127891, "W\0" },
{ 127904, 127946, "W\0" },
{ 127951, 127955, "W\0" },
{ 127968, 127984, "W\0" },
{ 127988, 127988, "W\0" },
{ 127992, 128062, "W\0" },
{ 128064, 128064, "W\0" },
{ 128066, 128252, "W\0" },
{ 128255, 128317, "W\0" },
{ 128331, 128334, "W\0" },
{ 128336, 128359, "W\0" },
{ 128378, 128378, "W\0" },
{ 128405, 128406, "W\0" },
{ 128420, 128420, "W\0" },
{ 128507, 128591, "W\0" },
{ 128640, 128709, "W\0" },
{ 128716, 128716, "W\0" },
{ 128720, 128722, "W\0" },
{ 128725, 128727, "W\0" },
{ 128728, 128732, "F\0" },
{ 128733, 128735, "W\0" },
{ 128747, 128748, "W\0" },
{ 128749, 128751, "F\0" },
{ 128756, 128764, "W\0" },
{ 128765, 128767, "F\0" },
{ 128884, 128895, "F\0" },
{ 128985, 128991, "F\0" },
{ 128992, 129003, "W\0" },
{ 129004, 129007, "F\0" },
{ 129008, 129008, "W\0" },
{ 129009, 129023, "F\0" },
{ 129036, 129039, "F\0" },
{ 129096, 129103, "F\0" },
{ 129114, 129119, "F\0" },
{ 129160, 129167, "F\0" },
{ 129198, 129199, "F\0" },
{ 129202, 129279, "F\0" },
{ 129292, 129338, "W\0" },
{ 129340, 129349, "W\0" },
{ 129351, 129535, "W\0" },
{ 129620, 129631, "F\0" },
{ 129646, 129647, "F\0" },
{ 129648, 129652, "W\0" },
{ 129653, 129655, "F\0" },
{ 129656, 129660, "W\0" },
{ 129661, 129663, "F\0" },
{ 129664, 129670, "W\0" },
{ 129671, 129679, "F\0" },
{ 129680, 129708, "W\0" },
{ 129709, 129711, "F\0" },
{ 129712, 129722, "W\0" },
{ 129723, 129727, "F\0" },
{ 129728, 129733, "W\0" },
{ 129734, 129743, "F\0" },
{ 129744, 129753, "W\0" },
{ 129754, 129759, "F\0" },
{ 129760, 129767, "W\0" },
{ 129768, 129775, "F\0" },
{ 129776, 129782, "W\0" },
{ 129783, 129791, "F\0" },
{ 129939, 129939, "F\0" },
{ 129995, 130031, "F\0" },
{ 130042, 131071, "F\0" },
{ 131072, 173791, "W\0" },
{ 173792, 173823, "F\0" },
{ 173824, 177976, "W\0" },
{ 177977, 177983, "F\0" },
{ 177984, 178205, "W\0" },
{ 178206, 178207, "F\0" },
{ 178208, 183969, "W\0" },
{ 183970, 183983, "F\0" },
{ 183984, 191456, "W\0" },
{ 191457, 194559, "F\0" },
{ 194560, 195101, "W\0" },
{ 195102, 196607, "F\0" },
{ 196608, 201546, "W\0" },
{ 201547, 917504, "F\0" },
{ 917506, 917535, "F\0" },
{ 917632, 917759, "F\0" },
{ 917760, 917999, "A\0" },
{ 918000, 983039, "F\0" },
{ 983040, 1048573, "A\0" },
{ 1048574, 1048575, "F\0" },
{ 1048576, 1114109, "A\0" },
{ 1114110, 1114111, "F\0" },
};
// clang-format on
const char* c11__u32_east_asian_width(int c) {
const char* data =
c11__search_u32_ranges(c,
kEastAsianWidthRanges,
sizeof(kEastAsianWidthRanges) / sizeof(c11_u32_range));
if(data == NULL) return "N";
return data;
}
static bool unicodedata_east_asian_width(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv sv = py_tosv(py_arg(0));
if(c11_sv__u8_length(sv) != 1) {
return TypeError("east_asian_width() expected a character, but string of length %d found",
c11_sv__u8_length(sv));
}
int u8bytes = c11__u8_header(sv.data[0], true);
if(u8bytes == 0) return ValueError("invalid utf-8 char: %c", sv.data[0]);
int value = c11__u8_value(u8bytes, sv.data);
const char* width = c11__u32_east_asian_width(value);
py_newstr(py_retval(), width);
return true;
}
void pk__add_module_unicodedata() {
py_Ref mod = py_newmodule("unicodedata");
py_bindfunc(mod, "east_asian_width", unicodedata_east_asian_width);
}
// src/modules\vmath.c
static bool isclose(float a, float b) { return dmath_fabs(a - b) < 1e-4; }
#define DEFINE_VEC_FIELD(name, T, Tc, field) \
static bool name##__##field(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
py_new##T(py_retval(), py_to##name(argv).field); \
return true; \
} \
static bool name##__with_##field(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
Tc val; \
if(!py_cast##T(&argv[1], &val)) return false; \
c11_##name v = py_to##name(argv); \
v.field = val; \
py_new##name(py_retval(), v); \
return true; \
}
#define DEFINE_BOOL_NE(name, f_eq) \
static bool name##__ne__(int argc, py_Ref argv) { \
f_eq(argc, argv); \
py_Ref ret = py_retval(); \
if(ret->type == tp_NotImplementedType) return true; \
ret->_bool = !ret->_bool; \
return true; \
}
void py_newvec2(py_OutRef out, c11_vec2 v) {
out->type = tp_vec2;
out->is_ptr = false;
out->_vec2 = v;
}
c11_vec2 py_tovec2(py_Ref self) {
assert(self->type == tp_vec2);
return self->_vec2;
}
void py_newvec2i(py_OutRef out, c11_vec2i v) {
out->type = tp_vec2i;
out->is_ptr = false;
out->_vec2i = v;
}
c11_vec2i py_tovec2i(py_Ref self) {
assert(self->type == tp_vec2i);
return self->_vec2i;
}
void py_newvec3(py_OutRef out, c11_vec3 v) {
out->type = tp_vec3;
out->is_ptr = false;
out->_vec3 = v;
}
c11_vec3 py_tovec3(py_Ref self) {
assert(self->type == tp_vec3);
return self->_vec3;
}
void py_newvec3i(py_OutRef out, c11_vec3i v) {
out->type = tp_vec3i;
out->is_ptr = false;
out->_vec3i = v;
}
c11_vec3i py_tovec3i(py_Ref self) {
assert(self->type == tp_vec3i);
return self->_vec3i;
}
void py_newvec4i(py_OutRef out, c11_vec4i v) {
out->type = tp_vec4i;
out->is_ptr = false;
out->_vec4i = v;
}
c11_vec4i py_tovec4i(py_Ref self) {
assert(self->type == tp_vec4i);
return self->_vec4i;
}
c11_mat3x3* py_newmat3x3(py_OutRef out) {
return py_newobject(out, tp_mat3x3, 0, sizeof(c11_mat3x3));
}
c11_mat3x3* py_tomat3x3(py_Ref self) {
assert(self->type == tp_mat3x3);
return py_touserdata(self);
}
static py_Ref _const(py_Type type, const char* name) {
return py_emplacedict(py_tpobject(type), py_name(name));
}
#define DEF_VECTOR_ELEMENT_WISE(D, T, name, op) \
static bool T##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
if(argv[1].type != tp_##T) { \
py_newnotimplemented(py_retval()); \
return true; \
} \
c11_##T a = py_to##T(&argv[0]); \
c11_##T b = py_to##T(&argv[1]); \
c11_##T res; \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] op b.data[i]; \
py_new##T(py_retval(), res); \
return true; \
}
#define DEF_VECTOR_OPS(D) \
static bool vec##D##__new__(int argc, py_Ref argv) { \
c11_vec##D res; \
if(argc == 2) { \
PY_CHECK_ARG_TYPE(1, tp_vec##D##i); \
c11_vec##D##i v = py_tovec##D##i(&argv[1]); \
for(int i = 0; i < D; i++) \
res.data[i] = v.data[i]; \
} else { \
PY_CHECK_ARGC(D + 1); \
for(int i = 0; i < D; i++) { \
if(!py_castfloat32(&argv[i + 1], &res.data[i])) return false; \
} \
} \
py_newvec##D(py_retval(), res); \
return true; \
} \
DEF_VECTOR_ELEMENT_WISE(D, vec##D, __add__, +) \
DEF_VECTOR_ELEMENT_WISE(D, vec##D, __sub__, -) \
static bool vec##D##__mul__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
c11_vec##D res; \
switch(argv[1].type) { \
case tp_vec##D: { \
c11_vec##D a = py_tovec##D(&argv[0]); \
c11_vec##D b = py_tovec##D(&argv[1]); \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] * b.data[i]; \
py_newvec##D(py_retval(), res); \
return true; \
} \
case tp_int: { \
c11_vec##D a = py_tovec##D(&argv[0]); \
py_i64 b = argv[1]._i64; \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] * b; \
py_newvec##D(py_retval(), res); \
return true; \
} \
case tp_float: { \
c11_vec##D a = py_tovec##D(&argv[0]); \
py_f64 b = argv[1]._f64; \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] * b; \
py_newvec##D(py_retval(), res); \
return true; \
} \
default: py_newnotimplemented(py_retval()); return true; \
} \
} \
static bool vec##D##__truediv__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
float divisor; \
if(!py_castfloat32(&argv[1], &divisor)) { \
py_clearexc(NULL); \
py_newnotimplemented(py_retval()); \
return true; \
} \
c11_vec##D res; \
c11_vec##D a = py_tovec##D(&argv[0]); \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] / divisor; \
py_newvec##D(py_retval(), res); \
return true; \
} \
static bool vec##D##__eq__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
if(argv[1].type != tp_vec##D) { \
py_newnotimplemented(py_retval()); \
return true; \
} \
c11_vec##D lhs = py_tovec##D(&argv[0]); \
c11_vec##D rhs = py_tovec##D(&argv[1]); \
bool ok = true; \
for(int i = 0; i < D; i++) { \
if(!isclose(lhs.data[i], rhs.data[i])) ok = false; \
} \
py_newbool(py_retval(), ok); \
return true; \
} \
DEFINE_BOOL_NE(vec##D, vec##D##__eq__) \
static bool vec##D##_length(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
c11_vec##D v = py_tovec##D(argv); \
float sum = 0; \
for(int i = 0; i < D; i++) \
sum += v.data[i] * v.data[i]; \
py_newfloat(py_retval(), dmath_sqrt(sum)); \
return true; \
} \
static bool vec##D##_length_squared(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
c11_vec##D v = py_tovec##D(argv); \
float sum = 0; \
for(int i = 0; i < D; i++) \
sum += v.data[i] * v.data[i]; \
py_newfloat(py_retval(), sum); \
return true; \
} \
static bool vec##D##_dot(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
PY_CHECK_ARG_TYPE(1, tp_vec##D); \
c11_vec##D a = py_tovec##D(&argv[0]); \
c11_vec##D b = py_tovec##D(&argv[1]); \
float sum = 0; \
for(int i = 0; i < D; i++) \
sum += a.data[i] * b.data[i]; \
py_newfloat(py_retval(), sum); \
return true; \
} \
static bool vec##D##_normalize(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
c11_vec##D self = py_tovec##D(argv); \
float len = 0; \
for(int i = 0; i < D; i++) \
len += self.data[i] * self.data[i]; \
if(isclose(len, 0)) return ZeroDivisionError("cannot normalize zero vector"); \
len = dmath_sqrt(len); \
c11_vec##D res; \
for(int i = 0; i < D; i++) \
res.data[i] = self.data[i] / len; \
py_newvec##D(py_retval(), res); \
return true; \
}
DEF_VECTOR_OPS(2)
DEF_VECTOR_OPS(3)
#define DEF_VECTOR_INT_OPS(D) \
static bool vec##D##i__new__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(D + 1); \
c11_vec##D##i res; \
for(int i = 0; i < D; i++) { \
if(!py_checkint(&argv[i + 1])) return false; \
res.data[i] = py_toint(&argv[i + 1]); \
} \
py_newvec##D##i(py_retval(), res); \
return true; \
} \
DEF_VECTOR_ELEMENT_WISE(D, vec##D##i, __add__, +) \
DEF_VECTOR_ELEMENT_WISE(D, vec##D##i, __sub__, -) \
static bool vec##D##i__mul__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
c11_vec##D##i res; \
switch(argv[1].type) { \
case tp_vec##D##i: { \
c11_vec##D##i a = py_tovec##D##i(&argv[0]); \
c11_vec##D##i b = py_tovec##D##i(&argv[1]); \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] * b.data[i]; \
py_newvec##D##i(py_retval(), res); \
return true; \
} \
case tp_int: { \
c11_vec##D##i a = py_tovec##D##i(&argv[0]); \
py_i64 b = argv[1]._i64; \
for(int i = 0; i < D; i++) \
res.data[i] = a.data[i] * b; \
py_newvec##D##i(py_retval(), res); \
return true; \
} \
default: py_newnotimplemented(py_retval()); return true; \
} \
} \
static bool vec##D##i__eq__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
if(argv[1].type != tp_vec##D##i) { \
py_newnotimplemented(py_retval()); \
return true; \
} \
c11_vec##D##i lhs = py_tovec##D##i(&argv[0]); \
c11_vec##D##i rhs = py_tovec##D##i(&argv[1]); \
bool ok = true; \
for(int i = 0; i < D; i++) { \
if(lhs.data[i] != rhs.data[i]) ok = false; \
} \
py_newbool(py_retval(), ok); \
return true; \
} \
DEFINE_BOOL_NE(vec##D##i, vec##D##i__eq__) \
static bool vec##D##i##_dot(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
PY_CHECK_ARG_TYPE(1, tp_vec##D##i); \
c11_vec##D##i a = py_tovec##D##i(&argv[0]); \
c11_vec##D##i b = py_tovec##D##i(&argv[1]); \
py_i64 sum = 0; \
for(int i = 0; i < D; i++) \
sum += a.data[i] * b.data[i]; \
py_newint(py_retval(), sum); \
return true; \
} \
static bool vec##D##i##__floordiv__(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
PY_CHECK_ARG_TYPE(1, tp_int); \
c11_vec##D##i a = py_tovec##D##i(&argv[0]); \
py_i64 b = py_toint(&argv[1]); \
for(int i = 0; i < D; i++) \
a.data[i] /= b; \
py_newvec##D##i(py_retval(), a); \
return true; \
}
DEF_VECTOR_INT_OPS(2)
DEF_VECTOR_INT_OPS(3)
DEF_VECTOR_INT_OPS(4)
static bool vec2i__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec2i v = py_tovec2i(argv);
uint64_t x_part = (uint32_t)v.x & 0xFFFFFFFF;
uint64_t y_part = (uint32_t)v.y & 0xFFFFFFFF;
uint64_t hash = (x_part << 32) | y_part;
py_newint(py_retval(), (py_i64)hash);
return true;
}
static bool vec3i__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec3i v = py_tovec3i(argv);
uint64_t x_part = (uint32_t)v.x & 0xFFFFFF;
uint64_t y_part = (uint32_t)v.y & 0xFFFFFF;
uint64_t z_part = (uint32_t)v.z & 0xFFFF;
uint64_t hash = (x_part << 40) | (y_part << 16) | z_part;
py_newint(py_retval(), (py_i64)hash);
return true;
}
static bool vec4i__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec4i v = py_tovec4i(argv);
uint64_t x_part = (uint32_t)v.x & 0xFFFF;
uint64_t y_part = (uint32_t)v.y & 0xFFFF;
uint64_t z_part = (uint32_t)v.z & 0xFFFF;
uint64_t w_part = (uint32_t)v.w & 0xFFFF;
uint64_t hash = (x_part << 48) | (y_part << 32) | (z_part << 16) | w_part;
py_newint(py_retval(), (py_i64)hash);
return true;
}
static bool vec2__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
char buf[64];
int size = snprintf(buf, 64, "vec2(%.4f, %.4f)", argv[0]._vec2.x, argv[0]._vec2.y);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
static bool vec2_rotate(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_f64 radians;
if(!py_castfloat(&argv[1], &radians)) return false;
double sr, cr;
dmath_sincos(radians, &sr, &cr);
c11_vec2 res;
res.x = argv[0]._vec2.x * cr - argv[0]._vec2.y * sr;
res.y = argv[0]._vec2.x * sr + argv[0]._vec2.y * cr;
py_newvec2(py_retval(), res);
return true;
}
static bool vec2_angle_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(0, tp_vec2);
PY_CHECK_ARG_TYPE(1, tp_vec2);
float val = dmath_atan2(argv[1]._vec2.y, argv[1]._vec2.x) - dmath_atan2(argv[0]._vec2.y, argv[0]._vec2.x);
if(val > DMATH_PI) val -= 2 * (float)DMATH_PI;
if(val < -DMATH_PI) val += 2 * (float)DMATH_PI;
py_newfloat(py_retval(), val);
return true;
}
static bool vec2_smoothdamp_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(6);
PY_CHECK_ARG_TYPE(0, tp_vec2); // current: vec2
PY_CHECK_ARG_TYPE(1, tp_vec2); // target: vec2
PY_CHECK_ARG_TYPE(2, tp_vec2); // current_velocity: vec2
float smoothTime;
if(!py_castfloat32(&argv[3], &smoothTime)) return false;
float maxSpeed;
if(!py_castfloat32(&argv[4], &maxSpeed)) return false;
float deltaTime;
if(!py_castfloat32(&argv[5], &deltaTime)) return false;
c11_vec2 current = argv[0]._vec2;
c11_vec2 target = argv[1]._vec2;
c11_vec2 currentVelocity = argv[2]._vec2;
// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector2.cs#L289
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = c11__max(0.0001F, smoothTime);
float omega = 2.0F / smoothTime;
float x = omega * deltaTime;
float exp = 1.0F / (1.0F + x + 0.48F * x * x + 0.235F * x * x * x);
float change_x = current.x - target.x;
float change_y = current.y - target.y;
c11_vec2 originalTo = target;
// Clamp maximum speed
float maxChange = maxSpeed * smoothTime;
float maxChangeSq = maxChange * maxChange;
float sqDist = change_x * change_x + change_y * change_y;
if(sqDist > maxChangeSq) {
float mag = dmath_sqrt(sqDist);
change_x = change_x / mag * maxChange;
change_y = change_y / mag * maxChange;
}
target.x = current.x - change_x;
target.y = current.y - change_y;
float temp_x = (currentVelocity.x + omega * change_x) * deltaTime;
float temp_y = (currentVelocity.y + omega * change_y) * deltaTime;
currentVelocity.x = (currentVelocity.x - omega * temp_x) * exp;
currentVelocity.y = (currentVelocity.y - omega * temp_y) * exp;
float output_x = target.x + (change_x + temp_x) * exp;
float output_y = target.y + (change_y + temp_y) * exp;
// Prevent overshooting
float origMinusCurrent_x = originalTo.x - current.x;
float origMinusCurrent_y = originalTo.y - current.y;
float outMinusOrig_x = output_x - originalTo.x;
float outMinusOrig_y = output_y - originalTo.y;
if(origMinusCurrent_x * outMinusOrig_x + origMinusCurrent_y * outMinusOrig_y > 0) {
output_x = originalTo.x;
output_y = originalTo.y;
currentVelocity.x = (output_x - originalTo.x) / deltaTime;
currentVelocity.y = (output_y - originalTo.y) / deltaTime;
}
py_Ref ret = py_retval();
py_Ref p = py_newtuple(ret, 2);
py_newvec2(&p[0],
(c11_vec2){
{output_x, output_y}
});
py_newvec2(&p[1], currentVelocity);
return true;
}
DEFINE_VEC_FIELD(vec2, float, py_f64, x)
DEFINE_VEC_FIELD(vec2, float, py_f64, y)
static bool vec2__with_z(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
float z;
if(!py_castfloat32(&argv[1], &z)) return false;
c11_vec3 v = {
{argv->_vec2.x, argv->_vec2.y, z}
};
py_newvec3(py_retval(), v);
return true;
}
/* mat3x3 */
static bool mat3x3__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(10);
c11_mat3x3* m = py_newmat3x3(py_retval());
for(int i = 0; i < 9; i++) {
py_f64 val;
if(!py_castfloat(&argv[i + 1], &val)) return false;
m->data[i] = val;
}
return true;
}
static bool mat3x3__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* m = py_tomat3x3(argv);
char buf[256];
const char* fmt =
"mat3x3(%.4f, %.4f, %.4f,\n %.4f, %.4f, %.4f,\n "
" %.4f, %.4f, %.4f)";
int size = snprintf(buf,
256,
fmt,
m->data[0],
m->data[1],
m->data[2],
m->data[3],
m->data[4],
m->data[5],
m->data[6],
m->data[7],
m->data[8]);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
static bool mat3x3__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_tuple);
c11_mat3x3* ud = py_tomat3x3(argv);
if(py_tuple_len(&argv[1]) != 2) return IndexError("expected a tuple of length 2");
py_Ref i = py_tuple_getitem(&argv[1], 0);
py_Ref j = py_tuple_getitem(&argv[1], 1);
if(!py_checktype(i, tp_int) || !py_checktype(j, tp_int)) return false;
if(i->_i64 < 0 || i->_i64 >= 3 || j->_i64 < 0 || j->_i64 >= 3) {
return IndexError("index out of range");
}
py_newfloat(py_retval(), ud->m[i->_i64][j->_i64]);
return true;
}
static bool mat3x3__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_tuple);
c11_mat3x3* ud = py_tomat3x3(argv);
if(py_tuple_len(&argv[1]) != 2) return IndexError("expected a tuple of length 2");
py_Ref i = py_tuple_getitem(&argv[1], 0);
py_Ref j = py_tuple_getitem(&argv[1], 1);
if(!py_checktype(i, tp_int) || !py_checktype(j, tp_int)) return false;
py_f64 val;
if(!py_castfloat(&argv[2], &val)) return false;
if(i->_i64 < 0 || i->_i64 >= 3 || j->_i64 < 0 || j->_i64 >= 3) {
return IndexError("index out of range");
}
ud->m[i->_i64][j->_i64] = val;
py_newnone(py_retval());
return true;
}
static bool mat3x3__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(argv[1].type != tp_mat3x3) {
py_newnotimplemented(py_retval());
return true;
}
c11_mat3x3* lhs = py_tomat3x3(argv);
c11_mat3x3* rhs = py_tomat3x3(&argv[1]);
for(int i = 0; i < 9; i++) {
if(!isclose(lhs->data[i], rhs->data[i])) {
py_newbool(py_retval(), false);
return true;
}
}
py_newbool(py_retval(), true);
return true;
}
DEFINE_BOOL_NE(mat3x3, mat3x3__eq__)
static void matmul(const c11_mat3x3* lhs, const c11_mat3x3* rhs, c11_mat3x3* restrict out) {
out->_11 = lhs->_11 * rhs->_11 + lhs->_12 * rhs->_21 + lhs->_13 * rhs->_31;
out->_12 = lhs->_11 * rhs->_12 + lhs->_12 * rhs->_22 + lhs->_13 * rhs->_32;
out->_13 = lhs->_11 * rhs->_13 + lhs->_12 * rhs->_23 + lhs->_13 * rhs->_33;
out->_21 = lhs->_21 * rhs->_11 + lhs->_22 * rhs->_21 + lhs->_23 * rhs->_31;
out->_22 = lhs->_21 * rhs->_12 + lhs->_22 * rhs->_22 + lhs->_23 * rhs->_32;
out->_23 = lhs->_21 * rhs->_13 + lhs->_22 * rhs->_23 + lhs->_23 * rhs->_33;
out->_31 = lhs->_31 * rhs->_11 + lhs->_32 * rhs->_21 + lhs->_33 * rhs->_31;
out->_32 = lhs->_31 * rhs->_12 + lhs->_32 * rhs->_22 + lhs->_33 * rhs->_32;
out->_33 = lhs->_31 * rhs->_13 + lhs->_32 * rhs->_23 + lhs->_33 * rhs->_33;
}
static float determinant(const c11_mat3x3* m) {
return m->_11 * (m->_22 * m->_33 - m->_23 * m->_32) -
m->_12 * (m->_21 * m->_33 - m->_23 * m->_31) +
m->_13 * (m->_21 * m->_32 - m->_22 * m->_31);
}
static bool inverse(const c11_mat3x3* m, c11_mat3x3* restrict out) {
float det = determinant(m);
if(isclose(det, 0)) return false;
float invdet = 1.0f / det;
out->_11 = (m->_22 * m->_33 - m->_23 * m->_32) * invdet;
out->_12 = (m->_13 * m->_32 - m->_12 * m->_33) * invdet;
out->_13 = (m->_12 * m->_23 - m->_13 * m->_22) * invdet;
out->_21 = (m->_23 * m->_31 - m->_21 * m->_33) * invdet;
out->_22 = (m->_11 * m->_33 - m->_13 * m->_31) * invdet;
out->_23 = (m->_13 * m->_21 - m->_11 * m->_23) * invdet;
out->_31 = (m->_21 * m->_32 - m->_22 * m->_31) * invdet;
out->_32 = (m->_12 * m->_31 - m->_11 * m->_32) * invdet;
out->_33 = (m->_11 * m->_22 - m->_12 * m->_21) * invdet;
return true;
}
static void trs(c11_vec2 t, float r, c11_vec2 s, c11_mat3x3* restrict out) {
double sr, cr;
dmath_sincos(r, &sr, &cr);
// clang-format off
*out = (c11_mat3x3){
._11 = s.x * cr, ._12 = -s.y * sr, ._13 = t.x,
._21 = s.x * sr, ._22 = s.y * cr, ._23 = t.y,
._31 = 0, ._32 = 0, ._33 = 1,
};
// clang-format on
}
static bool mat3x3__matmul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_mat3x3* lhs = py_tomat3x3(argv);
if(argv[1].type == tp_mat3x3) {
c11_mat3x3* rhs = py_tomat3x3(&argv[1]);
c11_mat3x3* out = py_newmat3x3(py_retval());
matmul(lhs, rhs, out);
} else if(argv[1].type == tp_vec3) {
c11_vec3 rhs = py_tovec3(&argv[1]);
c11_vec3 res;
res.x = lhs->_11 * rhs.x + lhs->_12 * rhs.y + lhs->_13 * rhs.z;
res.y = lhs->_21 * rhs.x + lhs->_22 * rhs.y + lhs->_23 * rhs.z;
res.z = lhs->_31 * rhs.x + lhs->_32 * rhs.y + lhs->_33 * rhs.z;
py_newvec3(py_retval(), res);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool mat3x3__invert__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_mat3x3* out = py_newmat3x3(py_retval());
if(inverse(ud, out)) return true;
return ZeroDivisionError("matrix is not invertible");
}
static bool mat3x3_matmul(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_mat3x3);
PY_CHECK_ARG_TYPE(1, tp_mat3x3);
PY_CHECK_ARG_TYPE(2, tp_mat3x3);
c11_mat3x3* lhs = py_tomat3x3(&argv[0]);
c11_mat3x3* rhs = py_tomat3x3(&argv[1]);
c11_mat3x3* out = py_tomat3x3(&argv[2]);
matmul(lhs, rhs, out);
py_newnone(py_retval());
return true;
}
static bool mat3x3_determinant(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
py_newfloat(py_retval(), determinant(ud));
return true;
}
static bool mat3x3_copy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_mat3x3* out = py_newmat3x3(py_retval());
*out = *ud;
return true;
}
static bool mat3x3_inverse(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_mat3x3* out = py_newmat3x3(py_retval());
if(inverse(ud, out)) return true;
return ZeroDivisionError("matrix is not invertible");
}
static bool mat3x3_copy_(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_mat3x3);
c11_mat3x3* self = py_tomat3x3(argv);
c11_mat3x3* other = py_tomat3x3(&argv[1]);
*self = *other;
py_newnone(py_retval());
return true;
}
static bool mat3x3_inverse_(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_mat3x3 res;
if(inverse(ud, &res)) {
*ud = res;
py_newnone(py_retval());
return true;
}
return ZeroDivisionError("matrix is not invertible");
}
static bool mat3x3_zeros_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
c11_mat3x3* out = py_newmat3x3(py_retval());
memset(out, 0, sizeof(c11_mat3x3));
return true;
}
static bool mat3x3_identity_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
c11_mat3x3* out = py_newmat3x3(py_retval());
// clang-format off
*out = (c11_mat3x3){
._11 = 1, ._12 = 0, ._13 = 0,
._21 = 0, ._22 = 1, ._23 = 0,
._31 = 0, ._32 = 0, ._33 = 1,
};
// clang-format on
return true;
}
static bool mat3x3_trs_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
py_f64 r;
if(!py_checktype(&argv[0], tp_vec2)) return false;
if(!py_castfloat(&argv[1], &r)) return false;
if(!py_checktype(&argv[2], tp_vec2)) return false;
c11_vec2 t = py_tovec2(&argv[0]);
c11_vec2 s = py_tovec2(&argv[2]);
c11_mat3x3* out = py_newmat3x3(py_retval());
trs(t, r, s, out);
return true;
}
static bool mat3x3_copy_trs_(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
c11_mat3x3* ud = py_tomat3x3(&argv[0]);
py_f64 r;
if(!py_checktype(&argv[1], tp_vec2)) return false;
if(!py_castfloat(&argv[2], &r)) return false;
if(!py_checktype(&argv[3], tp_vec2)) return false;
c11_vec2 t = py_tovec2(&argv[1]);
c11_vec2 s = py_tovec2(&argv[3]);
trs(t, r, s, ud);
py_newnone(py_retval());
return true;
}
static bool mat3x3_t(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_vec2 res;
res.x = ud->_13;
res.y = ud->_23;
py_newvec2(py_retval(), res);
return true;
}
static bool mat3x3_r(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
float r = dmath_atan2(ud->_21, ud->_11);
py_newfloat(py_retval(), r);
return true;
}
static bool mat3x3_s(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_mat3x3* ud = py_tomat3x3(argv);
c11_vec2 res;
res.x = dmath_sqrt(ud->_11 * ud->_11 + ud->_21 * ud->_21);
res.y = dmath_sqrt(ud->_12 * ud->_12 + ud->_22 * ud->_22);
py_newvec2(py_retval(), res);
return true;
}
static bool mat3x3_transform_point(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2);
c11_mat3x3* ud = py_tomat3x3(&argv[0]);
c11_vec2 p = py_tovec2(&argv[1]);
c11_vec2 res;
res.x = ud->_11 * p.x + ud->_12 * p.y + ud->_13;
res.y = ud->_21 * p.x + ud->_22 * p.y + ud->_23;
py_newvec2(py_retval(), res);
return true;
}
static bool mat3x3_transform_vector(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2);
c11_mat3x3* ud = py_tomat3x3(&argv[0]);
c11_vec2 p = py_tovec2(&argv[1]);
c11_vec2 res;
res.x = ud->_11 * p.x + ud->_12 * p.y;
res.y = ud->_21 * p.x + ud->_22 * p.y;
py_newvec2(py_retval(), res);
return true;
}
/* vec2i */
DEFINE_VEC_FIELD(vec2i, int, py_i64, x)
DEFINE_VEC_FIELD(vec2i, int, py_i64, y)
static bool vec2i__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec2i data = py_tovec2i(argv);
char buf[64];
int size = snprintf(buf, 64, "vec2i(%d, %d)", data.x, data.y);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
/* vec3i */
static bool vec3i__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec3i data = py_tovec3i(argv);
char buf[64];
int size = snprintf(buf, 64, "vec3i(%d, %d, %d)", data.x, data.y, data.z);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
DEFINE_VEC_FIELD(vec3i, int, py_i64, x)
DEFINE_VEC_FIELD(vec3i, int, py_i64, y)
DEFINE_VEC_FIELD(vec3i, int, py_i64, z)
/* vec4i */
static bool vec4i__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec4i data = py_tovec4i(argv);
char buf[64];
int size = snprintf(buf, 64, "vec4i(%d, %d, %d, %d)", data.x, data.y, data.z, data.w);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
DEFINE_VEC_FIELD(vec4i, int, py_i64, x)
DEFINE_VEC_FIELD(vec4i, int, py_i64, y)
DEFINE_VEC_FIELD(vec4i, int, py_i64, z)
DEFINE_VEC_FIELD(vec4i, int, py_i64, w)
/* vec3 */
static bool vec3__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec3 data = py_tovec3(argv);
char buf[64];
int size = snprintf(buf, 64, "vec3(%.4f, %.4f, %.4f)", data.x, data.y, data.z);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
DEFINE_VEC_FIELD(vec3, float, py_f64, x)
DEFINE_VEC_FIELD(vec3, float, py_f64, y)
DEFINE_VEC_FIELD(vec3, float, py_f64, z)
static bool vec3__xy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_vec3 data = py_tovec3(argv);
c11_vec2 res = {
{data.x, data.y}
};
py_newvec2(py_retval(), res);
return true;
}
static bool vec3__with_xy(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_vec2);
c11_vec2 xy = py_tovec2(&argv[1]);
c11_vec3 res = {
{xy.x, xy.y, py_tovec3(argv).z}
};
py_newvec3(py_retval(), res);
return true;
}
/* Color32 */
void py_newcolor32(py_OutRef out, c11_color32 color) {
out->type = tp_color32;
out->is_ptr = false;
out->_color32 = color;
}
c11_color32 py_tocolor32(py_Ref obj) {
assert(obj->type == tp_color32);
return obj->_color32;
}
static bool color32__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(5);
c11_color32 color;
for(int i = 1; i < 5; i++) {
PY_CHECK_ARG_TYPE(i, tp_int);
py_i64 val = py_toint(&argv[i]);
if(val < 0 || val > 255) return ValueError("color32 values must be between 0 and 255");
color.data[i - 1] = (unsigned char)val;
}
py_newcolor32(py_retval(), color);
return true;
}
#define DEFINE_COLOR32_FIELD(name) \
static bool color32__##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(1); \
c11_color32 color = py_tocolor32(argv); \
py_newint(py_retval(), color.name); \
return true; \
} \
static bool color32_with_##name(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
c11_color32 color = py_tocolor32(argv); \
PY_CHECK_ARG_TYPE(1, tp_int); \
py_i64 val = py_toint(&argv[1]); \
if(val < 0 || val > 255) { \
return ValueError("color32 values must be between 0 and 255"); \
} \
color.name = (unsigned char)val; \
py_newcolor32(py_retval(), color); \
return true; \
}
DEFINE_COLOR32_FIELD(r)
DEFINE_COLOR32_FIELD(g)
DEFINE_COLOR32_FIELD(b)
DEFINE_COLOR32_FIELD(a)
#undef DEFINE_COLOR32_FIELD
static bool color32_from_hex_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv hex = py_tosv(argv);
c11_color32 color;
int res;
if(hex.size == 7) {
res = sscanf(hex.data, "#%2hhx%2hhx%2hhx", &color.r, &color.g, &color.b);
if(res != 3) return ValueError("invalid hex color format");
color.a = 255;
} else {
res = sscanf(hex.data, "#%2hhx%2hhx%2hhx%2hhx", &color.r, &color.g, &color.b, &color.a);
if(res != 4) return ValueError("invalid hex color format");
}
py_newcolor32(py_retval(), color);
return true;
}
static bool color32_from_vec3_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_vec3);
c11_vec3 v = py_tovec3(argv);
c11_color32 color;
color.r = (unsigned char)(v.x * 255);
color.g = (unsigned char)(v.y * 255);
color.b = (unsigned char)(v.z * 255);
color.a = 255;
py_newcolor32(py_retval(), color);
return true;
}
static bool color32_from_vec3i_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_vec3i);
c11_vec3i v = py_tovec3i(argv);
c11_color32 color;
color.r = (unsigned char)v.x;
color.g = (unsigned char)v.y;
color.b = (unsigned char)v.z;
color.a = 255;
py_newcolor32(py_retval(), color);
return true;
}
static bool color32_to_hex(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
char buf[16];
int size;
if(color.a == 255) {
size = snprintf(buf, sizeof(buf), "#%02x%02x%02x", color.r, color.g, color.b);
} else {
size = snprintf(buf, sizeof(buf), "#%02x%02x%02x%02x", color.r, color.g, color.b, color.a);
}
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
void c11_color32_premult(c11_color32* color) {
if(color->a == 255) return;
float alpha = color->a / 255.0f;
color->r = (unsigned char)(color->r * alpha);
color->g = (unsigned char)(color->g * alpha);
color->b = (unsigned char)(color->b * alpha);
}
static bool color32_to_vec3(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
c11_color32_premult(&color);
c11_vec3 v;
v.x = (float)color.r / 255;
v.y = (float)color.g / 255;
v.z = (float)color.b / 255;
py_newvec3(py_retval(), v);
return true;
}
static bool color32_to_vec3i(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
c11_color32_premult(&color);
c11_vec3i v;
v.x = (int)color.r;
v.y = (int)color.g;
v.z = (int)color.b;
py_newvec3i(py_retval(), v);
return true;
}
static bool color32_to_rgb565(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
c11_color32_premult(&color);
uint16_t r = (color.r >> 3) & 0x1F;
uint16_t g = (color.g >> 2) & 0x3F;
uint16_t b = (color.b >> 3) & 0x1F;
uint16_t rgb565 = (r << 11) | (g << 5) | b;
py_newint(py_retval(), rgb565);
return true;
}
static bool color32__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(argv[1].type != tp_color32) {
py_newnotimplemented(py_retval());
return true;
}
c11_color32 lhs = py_tocolor32(&argv[0]);
c11_color32 rhs = py_tocolor32(&argv[1]);
bool eq = memcmp(&lhs, &rhs, sizeof(c11_color32)) == 0;
py_newbool(py_retval(), eq);
return true;
}
static bool color32__ne__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(argv[1].type != tp_color32) {
py_newnotimplemented(py_retval());
return true;
}
c11_color32 lhs = py_tocolor32(&argv[0]);
c11_color32 rhs = py_tocolor32(&argv[1]);
bool eq = memcmp(&lhs, &rhs, sizeof(c11_color32)) != 0;
py_newbool(py_retval(), eq);
return true;
}
static bool color32__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
char buf[64];
int size = snprintf(buf, 64, "color32(%d, %d, %d, %d)", color.r, color.g, color.b, color.a);
py_newstrv(py_retval(), (c11_sv){buf, size});
return true;
}
static bool color32__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_color32 color = py_tocolor32(argv);
uint32_t* color_int = (uint32_t*)&color;
py_newint(py_retval(), *color_int);
return true;
}
static bool color32_ansi_fg(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_color32 color = py_tocolor32(argv);
c11_color32_premult(&color);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_sv text = py_tosv(&argv[1]);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "\x1b[38;2;%d;%d;%dm%v\x1b[0m", color.r, color.g, color.b, text);
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool color32_ansi_bg(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_color32 color = py_tocolor32(argv);
c11_color32_premult(&color);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_sv text = py_tosv(&argv[1]);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "\x1b[48;2;%d;%d;%dm%v\x1b[0m", color.r, color.g, color.b, text);
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool vmath_rgb(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
c11_color32 color;
color.r = (unsigned char)py_toint(&argv[0]);
color.g = (unsigned char)py_toint(&argv[1]);
color.b = (unsigned char)py_toint(&argv[2]);
color.a = 255;
py_newcolor32(py_retval(), color);
return true;
}
static bool vmath_rgba(int argc, py_Ref argv) {
PY_CHECK_ARGC(4);
PY_CHECK_ARG_TYPE(0, tp_int);
PY_CHECK_ARG_TYPE(1, tp_int);
PY_CHECK_ARG_TYPE(2, tp_int);
PY_CHECK_ARG_TYPE(3, tp_float);
c11_color32 color;
color.r = (unsigned char)py_toint(&argv[0]);
color.g = (unsigned char)py_toint(&argv[1]);
color.b = (unsigned char)py_toint(&argv[2]);
color.a = (unsigned char)(py_tofloat(&argv[3]) * 255);
py_newcolor32(py_retval(), color);
return true;
}
static bool color32_alpha_blend_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(!py_checktype(&argv[0], tp_color32)) return false;
if(py_isnone(&argv[1])) {
py_assign(py_retval(), &argv[0]);
return true;
}
if(!py_checktype(&argv[1], tp_color32)) return false;
c11_color32 src = py_tocolor32(&argv[0]);
c11_color32 dst = py_tocolor32(&argv[1]);
float alpha = src.a / 255.0f;
c11_color32 res;
res.r = (unsigned char)(src.r * alpha + dst.r * (1 - alpha));
res.g = (unsigned char)(src.g * alpha + dst.g * (1 - alpha));
res.b = (unsigned char)(src.b * alpha + dst.b * (1 - alpha));
res.a = (unsigned char)(src.a + dst.a * (1 - alpha));
py_newcolor32(py_retval(), res);
return true;
}
void pk__add_module_vmath() {
py_Ref mod = py_newmodule("vmath");
py_Type vec2 = pk_newtype("vec2", tp_object, mod, NULL, false, true);
py_Type vec3 = pk_newtype("vec3", tp_object, mod, NULL, false, true);
py_Type vec2i = pk_newtype("vec2i", tp_object, mod, NULL, false, true);
py_Type vec3i = pk_newtype("vec3i", tp_object, mod, NULL, false, true);
py_Type vec4i = pk_newtype("vec4i", tp_object, mod, NULL, false, true);
py_Type mat3x3 = pk_newtype("mat3x3", tp_object, mod, NULL, false, true);
py_Type color32 = pk_newtype("color32", tp_object, mod, NULL, false, true);
py_setdict(mod, py_name("vec2"), py_tpobject(vec2));
py_setdict(mod, py_name("vec3"), py_tpobject(vec3));
py_setdict(mod, py_name("vec2i"), py_tpobject(vec2i));
py_setdict(mod, py_name("vec3i"), py_tpobject(vec3i));
py_setdict(mod, py_name("vec4i"), py_tpobject(vec4i));
py_setdict(mod, py_name("mat3x3"), py_tpobject(mat3x3));
py_setdict(mod, py_name("color32"), py_tpobject(color32));
c11__rtassert(vec2 == tp_vec2);
c11__rtassert(vec3 == tp_vec3);
c11__rtassert(vec2i == tp_vec2i);
c11__rtassert(vec3i == tp_vec3i);
c11__rtassert(vec4i == tp_vec4i);
c11__rtassert(mat3x3 == tp_mat3x3);
c11__rtassert(color32 == tp_color32);
/* vec2 */
py_bindmagic(vec2, __new__, vec2__new__);
py_bindmagic(vec2, __add__, vec2__add__);
py_bindmagic(vec2, __sub__, vec2__sub__);
py_bindmagic(vec2, __mul__, vec2__mul__);
py_bindmagic(vec2, __truediv__, vec2__truediv__);
py_bindmagic(vec2, __repr__, vec2__repr__);
py_bindmagic(vec2, __eq__, vec2__eq__);
py_bindmagic(vec2, __ne__, vec2__ne__);
py_bindmethod(vec2, "dot", vec2_dot);
py_bindmethod(vec2, "length", vec2_length);
py_bindmethod(vec2, "length_squared", vec2_length_squared);
py_bindmethod(vec2, "normalize", vec2_normalize);
py_bindmethod(vec2, "rotate", vec2_rotate);
// clang-format off
py_newvec2(_const(vec2, "ZERO"), (c11_vec2){{0, 0}});
py_newvec2(_const(vec2, "ONE"), (c11_vec2){{1, 1}});
py_newvec2(_const(vec2, "LEFT"), (c11_vec2){{-1, 0}});
py_newvec2(_const(vec2, "RIGHT"), (c11_vec2){{1, 0}});
py_newvec2(_const(vec2, "UP"), (c11_vec2){{0, -1}});
py_newvec2(_const(vec2, "DOWN"), (c11_vec2){{0, 1}});
// clang-format on
py_bindstaticmethod(vec2, "angle", vec2_angle_STATIC);
py_bindstaticmethod(vec2, "smooth_damp", vec2_smoothdamp_STATIC);
py_bindproperty(vec2, "x", vec2__x, NULL);
py_bindproperty(vec2, "y", vec2__y, NULL);
py_bindmethod(vec2, "with_x", vec2__with_x);
py_bindmethod(vec2, "with_y", vec2__with_y);
py_bindmethod(vec2, "with_z", vec2__with_z);
/* mat3x3 */
py_bindmagic(mat3x3, __new__, mat3x3__new__);
py_bindmagic(mat3x3, __repr__, mat3x3__repr__);
py_bindmagic(mat3x3, __getitem__, mat3x3__getitem__);
py_bindmagic(mat3x3, __setitem__, mat3x3__setitem__);
py_bindmagic(mat3x3, __matmul__, mat3x3__matmul__);
py_bindmagic(mat3x3, __invert__, mat3x3__invert__);
py_bindmagic(mat3x3, __eq__, mat3x3__eq__);
py_bindmagic(mat3x3, __ne__, mat3x3__ne__);
py_bindmethod(mat3x3, "matmul", mat3x3_matmul);
py_bindmethod(mat3x3, "determinant", mat3x3_determinant);
py_bindmethod(mat3x3, "copy", mat3x3_copy);
py_bindmethod(mat3x3, "inverse", mat3x3_inverse);
py_bindmethod(mat3x3, "copy_", mat3x3_copy_);
py_bindmethod(mat3x3, "inverse_", mat3x3_inverse_);
py_bindstaticmethod(mat3x3, "zeros", mat3x3_zeros_STATIC);
py_bindstaticmethod(mat3x3, "identity", mat3x3_identity_STATIC);
py_bindstaticmethod(mat3x3, "trs", mat3x3_trs_STATIC);
py_bindmethod(mat3x3, "copy_trs_", mat3x3_copy_trs_);
py_bindmethod(mat3x3, "t", mat3x3_t);
py_bindmethod(mat3x3, "r", mat3x3_r);
py_bindmethod(mat3x3, "s", mat3x3_s);
py_bindmethod(mat3x3, "transform_point", mat3x3_transform_point);
py_bindmethod(mat3x3, "transform_vector", mat3x3_transform_vector);
/* vec2i */
py_bindmagic(vec2i, __new__, vec2i__new__);
py_bindmagic(vec2i, __repr__, vec2i__repr__);
py_bindmagic(vec2i, __add__, vec2i__add__);
py_bindmagic(vec2i, __sub__, vec2i__sub__);
py_bindmagic(vec2i, __mul__, vec2i__mul__);
py_bindmagic(vec2i, __floordiv__, vec2i__floordiv__);
py_bindmagic(vec2i, __eq__, vec2i__eq__);
py_bindmagic(vec2i, __ne__, vec2i__ne__);
py_bindmagic(vec2i, __hash__, vec2i__hash__);
py_bindproperty(vec2i, "x", vec2i__x, NULL);
py_bindproperty(vec2i, "y", vec2i__y, NULL);
py_bindmethod(vec2i, "with_x", vec2i__with_x);
py_bindmethod(vec2i, "with_y", vec2i__with_y);
py_bindmethod(vec2i, "dot", vec2i_dot);
// clang-format off
py_newvec2i(_const(vec2i, "ZERO"), (c11_vec2i){{0, 0}});
py_newvec2i(_const(vec2i, "ONE"), (c11_vec2i){{1, 1}});
py_newvec2i(_const(vec2i, "LEFT"), (c11_vec2i){{-1, 0}});
py_newvec2i(_const(vec2i, "RIGHT"), (c11_vec2i){{1, 0}});
py_newvec2i(_const(vec2i, "UP"), (c11_vec2i){{0, -1}});
py_newvec2i(_const(vec2i, "DOWN"), (c11_vec2i){{0, 1}});
// clang-format on
/* vec3i */
py_bindmagic(vec3i, __new__, vec3i__new__);
py_bindmagic(vec3i, __repr__, vec3i__repr__);
py_bindmagic(vec3i, __add__, vec3i__add__);
py_bindmagic(vec3i, __sub__, vec3i__sub__);
py_bindmagic(vec3i, __mul__, vec3i__mul__);
py_bindmagic(vec3i, __floordiv__, vec3i__floordiv__);
py_bindmagic(vec3i, __eq__, vec3i__eq__);
py_bindmagic(vec3i, __ne__, vec3i__ne__);
py_bindmagic(vec3i, __hash__, vec3i__hash__);
py_bindproperty(vec3i, "x", vec3i__x, NULL);
py_bindproperty(vec3i, "y", vec3i__y, NULL);
py_bindproperty(vec3i, "z", vec3i__z, NULL);
py_bindmethod(vec3i, "with_x", vec3i__with_x);
py_bindmethod(vec3i, "with_y", vec3i__with_y);
py_bindmethod(vec3i, "with_z", vec3i__with_z);
py_bindmethod(vec3i, "dot", vec3i_dot);
py_newvec3i(_const(vec3i, "ZERO"),
(c11_vec3i){
{0, 0, 0}
});
py_newvec3i(_const(vec3i, "ONE"),
(c11_vec3i){
{1, 1, 1}
});
/* vec4i */
py_bindmagic(vec4i, __new__, vec4i__new__);
py_bindmagic(vec4i, __repr__, vec4i__repr__);
py_bindmagic(vec4i, __add__, vec4i__add__);
py_bindmagic(vec4i, __sub__, vec4i__sub__);
py_bindmagic(vec4i, __mul__, vec4i__mul__);
py_bindmagic(vec4i, __floordiv__, vec4i__floordiv__);
py_bindmagic(vec4i, __eq__, vec4i__eq__);
py_bindmagic(vec4i, __ne__, vec4i__ne__);
py_bindmagic(vec4i, __hash__, vec4i__hash__);
py_bindproperty(vec4i, "x", vec4i__x, NULL);
py_bindproperty(vec4i, "y", vec4i__y, NULL);
py_bindproperty(vec4i, "z", vec4i__z, NULL);
py_bindproperty(vec4i, "w", vec4i__w, NULL);
py_bindmethod(vec4i, "with_x", vec4i__with_x);
py_bindmethod(vec4i, "with_y", vec4i__with_y);
py_bindmethod(vec4i, "with_z", vec4i__with_z);
py_bindmethod(vec4i, "with_w", vec4i__with_w);
py_bindmethod(vec4i, "dot", vec4i_dot);
py_newvec4i(_const(vec4i, "ZERO"),
(c11_vec4i){
{0, 0, 0, 0}
});
py_newvec4i(_const(vec4i, "ONE"),
(c11_vec4i){
{1, 1, 1, 1}
});
/* vec3 */
py_bindmagic(vec3, __new__, vec3__new__);
py_bindmagic(vec3, __add__, vec3__add__);
py_bindmagic(vec3, __sub__, vec3__sub__);
py_bindmagic(vec3, __mul__, vec3__mul__);
py_bindmagic(vec3, __truediv__, vec3__truediv__);
py_bindmagic(vec3, __repr__, vec3__repr__);
py_bindmagic(vec3, __eq__, vec3__eq__);
py_bindmagic(vec3, __ne__, vec3__ne__);
py_bindmethod(vec3, "dot", vec3_dot);
py_bindmethod(vec3, "length", vec3_length);
py_bindmethod(vec3, "length_squared", vec3_length_squared);
py_bindmethod(vec3, "normalize", vec3_normalize);
py_bindproperty(vec3, "x", vec3__x, NULL);
py_bindproperty(vec3, "y", vec3__y, NULL);
py_bindproperty(vec3, "z", vec3__z, NULL);
py_bindproperty(vec3, "xy", vec3__xy, NULL);
py_bindmethod(vec3, "with_x", vec3__with_x);
py_bindmethod(vec3, "with_y", vec3__with_y);
py_bindmethod(vec3, "with_z", vec3__with_z);
py_bindmethod(vec3, "with_xy", vec3__with_xy);
py_newvec3(_const(vec3, "ZERO"),
(c11_vec3){
{0, 0, 0}
});
py_newvec3(_const(vec3, "ONE"),
(c11_vec3){
{1, 1, 1}
});
/* color32 */
py_bindmagic(color32, __new__, color32__new__);
py_bindmagic(color32, __repr__, color32__repr__);
py_bindmagic(color32, __eq__, color32__eq__);
py_bindmagic(color32, __ne__, color32__ne__);
py_bindmagic(color32, __hash__, color32__hash__);
py_bindproperty(color32, "r", color32__r, NULL);
py_bindproperty(color32, "g", color32__g, NULL);
py_bindproperty(color32, "b", color32__b, NULL);
py_bindproperty(color32, "a", color32__a, NULL);
py_bindmethod(color32, "with_r", color32_with_r);
py_bindmethod(color32, "with_g", color32_with_g);
py_bindmethod(color32, "with_b", color32_with_b);
py_bindmethod(color32, "with_a", color32_with_a);
py_bindstaticmethod(color32, "from_hex", color32_from_hex_STATIC);
py_bindstaticmethod(color32, "from_vec3", color32_from_vec3_STATIC);
py_bindstaticmethod(color32, "from_vec3i", color32_from_vec3i_STATIC);
py_bindmethod(color32, "to_hex", color32_to_hex);
py_bindmethod(color32, "to_vec3", color32_to_vec3);
py_bindmethod(color32, "to_vec3i", color32_to_vec3i);
py_bindmethod(color32, "to_rgb565", color32_to_rgb565);
py_bindmethod(color32, "ansi_fg", color32_ansi_fg);
py_bindmethod(color32, "ansi_bg", color32_ansi_bg);
py_bindfunc(mod, "rgb", vmath_rgb);
py_bindfunc(mod, "rgba", vmath_rgba);
py_bindstaticmethod(color32, "alpha_blend", color32_alpha_blend_STATIC);
}
#undef DEFINE_VEC_FIELD
#undef DEFINE_BOOL_NE
#undef DEF_VECTOR_ELEMENT_WISE
#undef DEF_VECTOR_OPS
#undef DEF_VECTOR_INT_OPS
// src/objects\bintree.c
void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config) {
self->key = key;
self->value = *value;
self->config = config;
self->left = NULL;
self->right = NULL;
}
void BinTree__dtor(BinTree* self) {
if(self->config->need_free_key) PK_FREE(self->key);
if(self->left) {
BinTree__dtor(self->left);
PK_FREE(self->left);
}
if(self->right) {
BinTree__dtor(self->right);
PK_FREE(self->right);
}
}
void BinTree__set(BinTree* self, void* key, py_Ref value) {
int cmp = self->config->f_cmp(key, self->key);
if(cmp < 0) {
if(self->left) {
BinTree__set(self->left, key, value);
} else {
self->left = PK_MALLOC(sizeof(BinTree));
BinTree__ctor(self->left, key, value, self->config);
}
} else if(cmp > 0) {
if(self->right) {
BinTree__set(self->right, key, value);
} else {
self->right = PK_MALLOC(sizeof(BinTree));
BinTree__ctor(self->right, key, value, self->config);
}
} else {
self->value = *value;
}
}
py_Ref BinTree__try_get(BinTree* self, void* key) {
int cmp = self->config->f_cmp(key, self->key);
if(cmp < 0) {
if(self->left) {
return BinTree__try_get(self->left, key);
} else {
return NULL;
}
} else if(cmp > 0) {
if(self->right) {
return BinTree__try_get(self->right, key);
} else {
return NULL;
}
} else {
return &self->value;
}
}
bool BinTree__contains(BinTree* self, void* key) { return BinTree__try_get(self, key) != NULL; }
void BinTree__apply_mark(BinTree* self, c11_vector* p_stack) {
pk__mark_value(&self->value);
if(self->left) BinTree__apply_mark(self->left, p_stack);
if(self->right) BinTree__apply_mark(self->right, p_stack);
}
// src/objects\codeobject.c
#include <stdint.h>
#include <assert.h>
void Bytecode__set_signed_arg(Bytecode* self, int arg) {
self->arg = (int16_t)arg;
if((int16_t)self->arg != arg) {
c11__abort("Bytecode__set_signed_arg(): %d is not representable in int16_t", arg);
}
}
bool Bytecode__is_forward_jump(const Bytecode* self) {
Opcode op = self->op;
return (op >= OP_JUMP_FORWARD && op <= OP_LOOP_BREAK) ||
(op == OP_FOR_ITER || op == OP_FOR_ITER_YIELD_VALUE);
}
void FuncDecl__dtor(FuncDecl* self) {
CodeObject__dtor(&self->code);
c11_vector__dtor(&self->args);
c11_vector__dtor(&self->kwargs);
c11_smallmap_n2d__dtor(&self->kw_to_index);
if(self->docstring) py_free(self->docstring);
}
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name) {
FuncDecl* self = PK_MALLOC(sizeof(FuncDecl));
self->rc.count = 1;
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
CodeObject__ctor(&self->code, src, name);
c11_vector__ctor(&self->args, sizeof(int32_t));
c11_vector__ctor(&self->kwargs, sizeof(FuncDeclKwArg));
self->starred_arg = -1;
self->starred_kwarg = -1;
self->nested = false;
self->docstring = NULL;
self->type = FuncType_UNSET;
c11_smallmap_n2d__ctor(&self->kw_to_index);
return self;
}
bool FuncDecl__is_duplicated_arg(const FuncDecl* decl, py_Name name) {
py_Name tmp_name;
c11__foreach(int, &decl->args, j) {
tmp_name = c11__getitem(py_Name, &decl->code.varnames, *j);
if(tmp_name == name) return true;
}
c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
tmp_name = c11__getitem(py_Name, &decl->code.varnames, kv->index);
if(tmp_name == name) return true;
}
if(decl->starred_arg != -1) {
tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_arg);
if(tmp_name == name) return true;
}
if(decl->starred_kwarg != -1) {
tmp_name = c11__getitem(py_Name, &decl->code.varnames, decl->starred_kwarg);
if(tmp_name == name) return true;
}
return false;
}
void FuncDecl__add_arg(FuncDecl* self, py_Name name) {
int32_t index = CodeObject__add_varname(&self->code, name);
c11_vector__push(int32_t, &self->args, index);
}
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value) {
int index = CodeObject__add_varname(&self->code, name);
c11_smallmap_n2d__set(&self->kw_to_index, name, index);
FuncDeclKwArg* item = c11_vector__emplace(&self->kwargs);
item->index = index;
item->key = name;
item->value = *value;
}
void FuncDecl__add_starred_arg(FuncDecl* self, py_Name name) {
int index = CodeObject__add_varname(&self->code, name);
self->starred_arg = index;
}
void FuncDecl__add_starred_kwarg(FuncDecl* self, py_Name name) {
int index = CodeObject__add_varname(&self->code, name);
self->starred_kwarg = index;
}
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name) {
self->src = src;
PK_INCREF(src);
self->name = c11_string__new2(name.data, name.size);
c11_vector__ctor(&self->codes, sizeof(Bytecode));
c11_vector__ctor(&self->codes_ex, sizeof(BytecodeEx));
c11_vector__ctor(&self->consts, sizeof(py_TValue));
c11_vector__ctor(&self->varnames, sizeof(py_Name));
c11_vector__ctor(&self->names, sizeof(py_Name));
self->nlocals = 0;
c11_smallmap_n2d__ctor(&self->varnames_inv);
c11_smallmap_n2d__ctor(&self->names_inv);
c11_vector__ctor(&self->blocks, sizeof(CodeBlock));
c11_vector__ctor(&self->func_decls, sizeof(FuncDecl_));
self->start_line = -1;
self->end_line = -1;
CodeBlock root_block = {CodeBlockType_NO_BLOCK, -1, 0, -1, -1};
c11_vector__push(CodeBlock, &self->blocks, root_block);
}
void CodeObject__dtor(CodeObject* self) {
PK_DECREF(self->src);
c11_string__delete(self->name);
c11_vector__dtor(&self->codes);
c11_vector__dtor(&self->codes_ex);
c11_vector__dtor(&self->consts);
c11_vector__dtor(&self->varnames);
c11_vector__dtor(&self->names);
c11_smallmap_n2d__dtor(&self->varnames_inv);
c11_smallmap_n2d__dtor(&self->names_inv);
c11_vector__dtor(&self->blocks);
for(int i = 0; i < self->func_decls.length; i++) {
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
PK_DECREF(decl);
}
c11_vector__dtor(&self->func_decls);
}
void Function__ctor(Function* self, FuncDecl_ decl, py_GlobalRef module, py_Ref globals) {
PK_INCREF(decl);
self->decl = decl;
self->module = module;
self->globals = globals != NULL ? *globals : *py_NIL();
self->closure = NULL;
self->clazz = NULL;
self->cfunc = NULL;
}
int CodeObject__add_varname(CodeObject* self, py_Name name) {
int index = c11_smallmap_n2d__get(&self->varnames_inv, name, -1);
if(index >= 0) return index;
c11_vector__push(py_Name, &self->varnames, name);
self->nlocals++;
index = self->varnames.length - 1;
c11_smallmap_n2d__set(&self->varnames_inv, name, index);
return index;
}
int CodeObject__add_name(CodeObject* self, py_Name name) {
int index = c11_smallmap_n2d__get(&self->names_inv, name, -1);
if(index >= 0) return index;
c11_vector__push(py_Name, &self->names, name);
index = self->names.length - 1;
c11_smallmap_n2d__set(&self->names_inv, name, index);
return index;
}
void Function__dtor(Function* self) {
// printf("%s() in %s freed!\n", self->decl->code.name->data,
// self->decl->code.src->filename->data);
PK_DECREF(self->decl);
if(self->closure) NameDict__delete(self->closure);
memset(self, 0, sizeof(Function));
}
// src/objects\codeobject_ser.c
// Magic number for CodeObject serialization: "CO" = 0x434F
#define CODEOBJECT_MAGIC 0x434F
#define CODEOBJECT_VER_MAJOR 1
#define CODEOBJECT_VER_MINOR 0
#define CODEOBJECT_VER_MINOR_MIN 0
// Forward declarations
static void FuncDecl__serialize(c11_serializer* s,
const FuncDecl* decl,
const struct SourceData* parent_src);
static FuncDecl_ FuncDecl__deserialize(c11_deserializer* d, SourceData_ embedded_src);
static void CodeObject__serialize(c11_serializer* s,
const CodeObject* co,
const struct SourceData* parent_src);
static CodeObject CodeObject__deserialize(c11_deserializer* d, const char* filename, SourceData_ embedded_src);
// Serialize a py_TValue constant
static void TValue__serialize(c11_serializer* s, py_Ref val) {
c11_serializer__write_type(s, val->type);
// 1. co_consts: int | float | str
// 2. function defaults: see `read_literal()` in compiler.c
switch(val->type) {
case tp_int: c11_serializer__write_i64(s, val->_i64); break;
case tp_float: c11_serializer__write_f64(s, val->_f64); break;
case tp_str: {
c11_sv sv = py_tosv((py_Ref)val);
c11_serializer__write_i32(s, sv.size);
c11_serializer__write_bytes(s, sv.data, sv.size);
break;
}
case tp_bool: {
bool value = py_tobool(val);
c11_serializer__write_i8(s, value ? 1 : 0);
break;
}
case tp_NoneType: break;
case tp_ellipsis: break;
case tp_tuple: {
int len = py_tuple_len(val);
c11_serializer__write_i32(s, len);
for(int i = 0; i < len; i++) {
py_Ref item = py_tuple_getitem(val, i);
TValue__serialize(s, item);
}
break;
}
default: c11__abort("TValue__serialize: invalid type '%s'", py_tpname(val->type));
}
}
// Deserialize a py_TValue constant
static void TValue__deserialize(c11_deserializer* d, py_OutRef out) {
py_Type type = c11_deserializer__read_type(d);
switch(type) {
case tp_int: {
py_i64 v = c11_deserializer__read_i64(d);
py_newint(out, v);
break;
}
case tp_float: {
py_f64 v = c11_deserializer__read_f64(d);
py_newfloat(out, v);
break;
}
case tp_str: {
int size = c11_deserializer__read_i32(d);
char* dst = py_newstrn(out, size);
char* src = c11_deserializer__read_bytes(d, size);
memcpy(dst, src, size);
break;
}
case tp_bool: {
bool v = c11_deserializer__read_i8(d) != 0;
py_newbool(out, v);
break;
}
case tp_NoneType: {
py_newnone(out);
break;
}
case tp_ellipsis: {
py_newellipsis(out);
break;
}
case tp_tuple: {
int len = c11_deserializer__read_i32(d);
py_newtuple(out, len);
for(int i = 0; i < len; i++) {
py_ItemRef item = py_tuple_getitem(out, i);
TValue__deserialize(d, item);
}
break;
}
default:
c11__abort("TValue__deserialize: invalid type '%s'", py_tpname(type));
}
}
// Serialize CodeObject
static void CodeObject__serialize(c11_serializer* s,
const CodeObject* co,
const struct SourceData* parent_src) {
// SourceData
if(parent_src) {
c11__rtassert(co->src == parent_src);
}
// name
c11_serializer__write_cstr(s, co->name->data);
// codes
_Static_assert(sizeof(Bytecode) == sizeof(uint16_t) * 2, "");
c11_serializer__write_i32(s, co->codes.length);
c11_serializer__write_mark(s, '[');
c11_serializer__write_bytes(s, co->codes.data, co->codes.length * sizeof(Bytecode));
c11_serializer__write_mark(s, ']');
// codes_ex
_Static_assert(sizeof(BytecodeEx) == sizeof(int32_t) * 2, "");
c11_serializer__write_i32(s, co->codes_ex.length);
c11_serializer__write_mark(s, '[');
c11_serializer__write_bytes(s, co->codes_ex.data, co->codes_ex.length * sizeof(BytecodeEx));
c11_serializer__write_mark(s, ']');
// consts
c11_serializer__write_i32(s, co->consts.length);
c11_serializer__write_mark(s, '[');
for(int i = 0; i < co->consts.length; i++) {
py_Ref val = c11__at(py_TValue, &co->consts, i);
TValue__serialize(s, val);
}
c11_serializer__write_mark(s, ']');
// varnames (as cstr via py_name2str)
c11_serializer__write_i32(s, co->varnames.length);
c11_serializer__write_mark(s, '[');
for(int i = 0; i < co->varnames.length; i++) {
py_Name name = c11__getitem(py_Name, &co->varnames, i);
c11_serializer__write_cstr(s, py_name2str(name));
}
c11_serializer__write_mark(s, ']');
// names (as cstr via py_name2str)
c11_serializer__write_i32(s, co->names.length);
c11_serializer__write_mark(s, '[');
for(int i = 0; i < co->names.length; i++) {
py_Name name = c11__getitem(py_Name, &co->names, i);
c11_serializer__write_cstr(s, py_name2str(name));
}
c11_serializer__write_mark(s, ']');
// nlocals
c11_serializer__write_i32(s, co->nlocals);
// blocks
_Static_assert(sizeof(CodeBlock) == sizeof(int32_t) * 5, "");
c11_serializer__write_i32(s, co->blocks.length);
c11_serializer__write_mark(s, '[');
c11_serializer__write_bytes(s, co->blocks.data, co->blocks.length * sizeof(CodeBlock));
c11_serializer__write_mark(s, ']');
// func_decls
c11_serializer__write_i32(s, co->func_decls.length);
c11_serializer__write_mark(s, '[');
for(int i = 0; i < co->func_decls.length; i++) {
const FuncDecl* decl = c11__getitem(FuncDecl_, &co->func_decls, i);
FuncDecl__serialize(s, decl, co->src);
c11_serializer__write_mark(s, '|');
}
c11_serializer__write_mark(s, ']');
// start_line, end_line
c11_serializer__write_i32(s, co->start_line);
c11_serializer__write_i32(s, co->end_line);
}
// Deserialize CodeObject (initialize co before calling)
static CodeObject CodeObject__deserialize(c11_deserializer* d, const char* filename, SourceData_ embedded_src) {
CodeObject co;
// SourceData
SourceData_ src;
if(embedded_src != NULL) {
c11__rtassert(filename == NULL);
src = embedded_src;
PK_INCREF(src);
} else {
c11__rtassert(filename != NULL);
src = SourceData__rcnew(NULL, filename, EXEC_MODE, false);
}
// name
const char* name = c11_deserializer__read_cstr(d);
c11_sv name_sv = {name, strlen(name)};
// Initialize the CodeObject
CodeObject__ctor(&co, src, name_sv);
PK_DECREF(src); // CodeObject__ctor increments ref count
// Clear the default root block that CodeObject__ctor adds
c11_vector__clear(&co.blocks);
// codes
int codes_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
c11_vector__extend(&co.codes,
c11_deserializer__read_bytes(d, codes_len * sizeof(Bytecode)),
codes_len);
c11_deserializer__consume_mark(d, ']');
// codes_ex
int codes_ex_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
c11_vector__extend(&co.codes_ex,
c11_deserializer__read_bytes(d, codes_ex_len * sizeof(BytecodeEx)),
codes_ex_len);
c11_deserializer__consume_mark(d, ']');
// consts
int consts_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
for(int i = 0; i < consts_len; i++) {
py_Ref p_val = c11_vector__emplace(&co.consts);
TValue__deserialize(d, p_val);
}
c11_deserializer__consume_mark(d, ']');
// varnames
int varnames_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
for(int i = 0; i < varnames_len; i++) {
const char* s = c11_deserializer__read_cstr(d);
py_Name n = py_name(s);
c11_vector__push(py_Name, &co.varnames, n);
c11_smallmap_n2d__set(&co.varnames_inv, n, i);
}
c11_deserializer__consume_mark(d, ']');
// names
int names_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
for(int i = 0; i < names_len; i++) {
const char* s = c11_deserializer__read_cstr(d);
py_Name n = py_name(s);
c11_vector__push(py_Name, &co.names, n);
c11_smallmap_n2d__set(&co.names_inv, n, i);
}
c11_deserializer__consume_mark(d, ']');
// nlocals
co.nlocals = c11_deserializer__read_i32(d);
// blocks
int blocks_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
c11_vector__extend(&co.blocks,
c11_deserializer__read_bytes(d, blocks_len * sizeof(CodeBlock)),
blocks_len);
c11_deserializer__consume_mark(d, ']');
// func_decls
int func_decls_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
for(int i = 0; i < func_decls_len; i++) {
FuncDecl_ decl = FuncDecl__deserialize(d, src);
c11_vector__push(FuncDecl_, &co.func_decls, decl);
c11_deserializer__consume_mark(d, '|');
}
c11_deserializer__consume_mark(d, ']');
// start_line, end_line
co.start_line = c11_deserializer__read_i32(d);
co.end_line = c11_deserializer__read_i32(d);
return co;
}
// Serialize FuncDecl
static void FuncDecl__serialize(c11_serializer* s,
const FuncDecl* decl,
const struct SourceData* parent_src) {
// CodeObject (embedded)
c11_serializer__write_mark(s, '{');
CodeObject__serialize(s, &decl->code, parent_src);
c11_serializer__write_mark(s, '}');
// args
c11_serializer__write_i32(s, decl->args.length);
c11_serializer__write_mark(s, '[');
c11_serializer__write_bytes(s, decl->args.data, decl->args.length * sizeof(int32_t));
c11_serializer__write_mark(s, ']');
// kwargs
c11_serializer__write_i32(s, decl->kwargs.length);
c11_serializer__write_mark(s, '[');
for(int i = 0; i < decl->kwargs.length; i++) {
FuncDeclKwArg* kw = c11__at(FuncDeclKwArg, &decl->kwargs, i);
c11_serializer__write_i32(s, kw->index);
c11_serializer__write_cstr(s, py_name2str(kw->key));
TValue__serialize(s, &kw->value);
}
c11_serializer__write_mark(s, ']');
// starred_arg, starred_kwarg
c11_serializer__write_i32(s, decl->starred_arg);
c11_serializer__write_i32(s, decl->starred_kwarg);
// nested
c11_serializer__write_i8(s, decl->nested ? 1 : 0);
// docstring
int has_docstring = decl->docstring != NULL ? 1 : 0;
c11_serializer__write_i8(s, has_docstring);
if(has_docstring) c11_serializer__write_cstr(s, decl->docstring);
// type
c11_serializer__write_i8(s, (int8_t)decl->type);
}
// Deserialize FuncDecl
static FuncDecl_ FuncDecl__deserialize(c11_deserializer* d, SourceData_ embedded_src) {
FuncDecl_ self = PK_MALLOC(sizeof(FuncDecl));
self->rc.count = 1;
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
c11_vector__ctor(&self->args, sizeof(int32_t));
c11_vector__ctor(&self->kwargs, sizeof(FuncDeclKwArg));
c11_smallmap_n2d__ctor(&self->kw_to_index);
// CodeObject (embedded)
c11_deserializer__consume_mark(d, '{');
self->code = CodeObject__deserialize(d, NULL, embedded_src);
c11_deserializer__consume_mark(d, '}');
// args
int args_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
c11_vector__extend(&self->args,
c11_deserializer__read_bytes(d, args_len * sizeof(int32_t)),
args_len);
c11_deserializer__consume_mark(d, ']');
// kwargs
int kwargs_len = c11_deserializer__read_i32(d);
c11_deserializer__consume_mark(d, '[');
for(int i = 0; i < kwargs_len; i++) {
FuncDeclKwArg* kw = c11_vector__emplace(&self->kwargs);
kw->index = c11_deserializer__read_i32(d);
const char* key_str = c11_deserializer__read_cstr(d);
kw->key = py_name(key_str);
TValue__deserialize(d, &kw->value);
c11_smallmap_n2d__set(&self->kw_to_index, kw->key, kw->index);
}
c11_deserializer__consume_mark(d, ']');
// starred_arg
self->starred_arg = c11_deserializer__read_i32(d);
// starred_kwarg
self->starred_kwarg = c11_deserializer__read_i32(d);
// nested
self->nested = c11_deserializer__read_i8(d) != 0;
// docstring
int has_docstring = c11_deserializer__read_i8(d);
if(has_docstring) {
const char* docstring = c11_deserializer__read_cstr(d);
self->docstring = c11_strdup(docstring);
} else {
self->docstring = NULL;
}
// type
self->type = (FuncType)c11_deserializer__read_i8(d);
return self;
}
// Public API: Serialize CodeObject to bytes
void* CodeObject__dumps(const CodeObject* co, int* size) {
c11_serializer s;
c11_serializer__ctor(&s, CODEOBJECT_MAGIC, CODEOBJECT_VER_MAJOR, CODEOBJECT_VER_MINOR);
CodeObject__serialize(&s, co, NULL);
return c11_serializer__submit(&s, size);
}
// Public API: Deserialize CodeObject from bytes
// Returns error message or NULL on success
char* CodeObject__loads(const void* data, int size, const char* filename, CodeObject* out) {
c11_deserializer d;
c11_deserializer__ctor(&d, data, size);
if(!c11_deserializer__check_header(&d,
CODEOBJECT_MAGIC,
CODEOBJECT_VER_MAJOR,
CODEOBJECT_VER_MINOR_MIN)) {
char* error_msg = c11_strdup(d.error_msg);
c11_deserializer__dtor(&d);
return error_msg;
}
*out = CodeObject__deserialize(&d, filename, NULL);
c11_deserializer__dtor(&d);
return NULL;
}
#undef CODEOBJECT_MAGIC
#undef CODEOBJECT_VER_MAJOR
#undef CODEOBJECT_VER_MINOR
#undef CODEOBJECT_VER_MINOR_MIN
// src/objects\container.c
#define FIXEDHASH_T__SOURCE
#define K py_Name
#define V py_TValue
#define NAME CachedNames
#if !defined(FIXEDHASH_T__HEADER) && !defined(FIXEDHASH_T__SOURCE)
#include "pocketpy/common/chunkedvector.h"
#include "pocketpy/config.h"
#include <stdint.h>
#define FIXEDHASH_T__HEADER
#define FIXEDHASH_T__SOURCE
/* Input */
#define K int
#define V float
#define NAME c11_fixedhash_d2f
#endif
/* Optional Input */
#ifndef hash
#define hash(a) ((uint64_t)(a))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temporary macros */
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(NAME, _KV)
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
#ifdef FIXEDHASH_T__HEADER
/* Declaration */
typedef struct {
uint64_t hash;
K key;
V val;
} KV;
typedef struct {
int length;
uint16_t indices[0x10000];
c11_chunkedvector /*T=FixedHashEntry*/ entries;
} NAME;
void METHOD(ctor)(NAME* self);
void METHOD(dtor)(NAME* self);
NAME* METHOD(new)();
void METHOD(delete)(NAME* self);
void METHOD(set)(NAME* self, K key, V* value);
V* METHOD(try_get)(NAME* self, K key);
bool METHOD(contains)(NAME* self, K key);
#endif
#ifdef FIXEDHASH_T__SOURCE
/* Implementation */
void METHOD(ctor)(NAME* self) {
self->length = 0;
memset(self->indices, 0xFF, sizeof(self->indices));
c11_chunkedvector__ctor(&self->entries, sizeof(KV), 0);
}
void METHOD(dtor)(NAME* self) { c11_chunkedvector__dtor(&self->entries); }
NAME* METHOD(new)() {
NAME* self = PK_MALLOC(sizeof(NAME));
METHOD(ctor)(self);
return self;
}
void METHOD(delete)(NAME* self) {
METHOD(dtor)(self);
PK_FREE(self);
}
void METHOD(set)(NAME* self, K key, V* value) {
uint64_t hash_value = hash(key);
int index = (uint16_t)(hash_value & 0xFFFF);
while(self->indices[index] != 0xFFFF) {
KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
if(equal(entry->key, key)) {
entry->val = *value;
return;
}
index = ((5 * index) + 1) & 0xFFFF;
}
if(self->length >= 65000) abort();
KV* kv = c11_chunkedvector__emplace(&self->entries);
kv->hash = hash_value;
kv->key = key;
kv->val = *value;
self->indices[index] = self->entries.length - 1;
self->length++;
}
V* METHOD(try_get)(NAME* self, K key) {
uint64_t hash_value = hash(key);
int index = (uint16_t)(hash_value & 0xFFFF);
while(self->indices[index] != 0xFFFF) {
KV* entry = c11_chunkedvector__at(&self->entries, self->indices[index]);
if(equal(entry->key, key)) return &entry->val;
index = ((5 * index) + 1) & 0xFFFF;
}
return NULL;
}
bool METHOD(contains)(NAME* self, K key) {
V* value = METHOD(try_get)(self, key);
return value != NULL;
}
#endif
/* Undefine all macros */
#undef KV
#undef METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef NAME
#undef less
#undef partial_less
#undef equal
#undef hash
#undef FIXEDHASH_T__SOURCE
// src/objects\namedict.c
#include <stdint.h>
#include <string.h>
#include <assert.h>
// https://jfdube.wordpress.com/2011/10/12/hashing-strings-and-pointers-avoiding-common-pitfalls/
uintptr_t ThomasWangInt32Hash(void* Ptr) {
// Here we think only the lower 32 bits are useful
uint32_t Value = (uint32_t)(uintptr_t)Ptr;
Value = ~Value + (Value << 15);
Value = Value ^ (Value >> 12);
Value = Value + (Value << 2);
Value = Value ^ (Value >> 4);
Value = Value * 2057;
Value = Value ^ (Value >> 16);
return Value;
}
#define HASH_KEY(__k) ThomasWangInt32Hash(__k)
#define HASH_PROBE_0(__k, ok, i) \
ok = false; \
i = HASH_KEY(__k) & self->mask; \
do { \
if(self->items[i].key == (__k)) { \
ok = true; \
break; \
} \
if(self->items[i].key == NULL) break; \
i = (i + 1) & self->mask; \
} while(true);
#define HASH_PROBE_1(__k, ok, i) \
ok = false; \
i = HASH_KEY(__k) & self->mask; \
while(self->items[i].key != NULL) { \
if(self->items[i].key == (__k)) { \
ok = true; \
break; \
} \
i = (i + 1) & self->mask; \
}
static void NameDict__set_capacity_and_alloc_items(NameDict* self, int val) {
self->capacity = val;
self->critical_size = val * self->load_factor;
self->mask = (uintptr_t)val - 1;
self->items = PK_MALLOC(self->capacity * sizeof(NameDict_KV));
memset(self->items, 0, self->capacity * sizeof(NameDict_KV));
}
static void NameDict__rehash_2x(NameDict* self) {
NameDict_KV* old_items = self->items;
int old_capacity = self->capacity;
NameDict__set_capacity_and_alloc_items(self, self->capacity * 2);
for(int i = 0; i < old_capacity; i++) {
if(old_items[i].key == NULL) continue;
bool ok;
uintptr_t j;
HASH_PROBE_1(old_items[i].key, ok, j);
c11__rtassert(!ok);
self->items[j] = old_items[i];
}
PK_FREE(old_items);
}
NameDict* NameDict__new(float load_factor) {
NameDict* p = PK_MALLOC(sizeof(NameDict));
NameDict__ctor(p, load_factor);
return p;
}
void NameDict__delete(NameDict* self) {
NameDict__dtor(self);
PK_FREE(self);
}
void NameDict__ctor(NameDict* self, float load_factor) {
assert(load_factor > 0.0f && load_factor < 1.0f);
self->length = 0;
self->load_factor = load_factor;
NameDict__set_capacity_and_alloc_items(self, 4);
}
void NameDict__dtor(NameDict* self) { PK_FREE(self->items); }
py_TValue* NameDict__try_get(NameDict* self, py_Name key) {
bool ok;
uintptr_t i;
HASH_PROBE_0(key, ok, i);
if(!ok) return NULL;
return &self->items[i].value;
}
bool NameDict__contains(NameDict* self, py_Name key) {
bool ok;
uintptr_t i;
HASH_PROBE_0(key, ok, i);
return ok;
}
void NameDict__set(NameDict* self, py_Name key, py_TValue* val) {
bool ok;
uintptr_t i;
HASH_PROBE_1(key, ok, i);
if(!ok) {
self->length++;
if(self->length > self->critical_size) {
NameDict__rehash_2x(self);
HASH_PROBE_1(key, ok, i);
}
self->items[i].key = key;
}
self->items[i].value = *val;
}
bool NameDict__del(NameDict* self, py_Name key) {
bool ok;
uintptr_t i;
HASH_PROBE_0(key, ok, i);
if(!ok) return false;
self->items[i].key = NULL;
self->items[i].value = *py_NIL();
self->length--;
/* tidy */
uintptr_t posToRemove = i;
uintptr_t posToShift = posToRemove;
while(true) {
posToShift = (posToShift + 1) & self->mask;
if(self->items[posToShift].key == NULL) break;
uintptr_t hash_z = HASH_KEY(self->items[posToShift].key);
uintptr_t insertPos = hash_z & self->mask;
bool cond1 = insertPos <= posToRemove;
bool cond2 = posToRemove <= posToShift;
if((cond1 && cond2) ||
// chain wrapped around capacity
(posToShift < insertPos && (cond1 || cond2))) {
NameDict_KV tmp = self->items[posToRemove];
assert(tmp.key == NULL);
self->items[posToRemove] = self->items[posToShift];
self->items[posToShift] = tmp;
posToRemove = posToShift;
}
}
return true;
}
void NameDict__clear(NameDict* self) {
for(int i = 0; i < self->capacity; i++) {
self->items[i].key = NULL;
self->items[i].value = *py_NIL();
}
self->length = 0;
}
#undef HASH_PROBE_0
#undef HASH_PROBE_1
#undef HASH_KEY
// src/objects\object.c
#include <assert.h>
PK_INLINE void* PyObject__userdata(PyObject* self) {
return self->flex + PK_OBJ_SLOTS_SIZE(self->slots);
}
PK_INLINE NameDict* PyObject__dict(PyObject* self) {
assert(self->slots == -1);
return (NameDict*)(self->flex);
}
PK_INLINE py_TValue* PyObject__slots(PyObject* self) {
assert(self->slots >= 0);
return (py_TValue*)(self->flex);
}
// src/public\Bindings.c
void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
py_Ref tmp = py_pushtmp();
py_Name name = py_newfunction(tmp, sig, f, NULL, 0);
py_setdict(obj, name, tmp);
py_pop();
}
void py_bindmethod(py_Type type, const char* name, py_CFunction f) {
py_TValue tmp;
py_newnativefunc(&tmp, f);
py_setdict(py_tpobject(type), py_name(name), &tmp);
}
void py_bindstaticmethod(py_Type type, const char* name, py_CFunction f) {
py_TValue tmp;
py_newnativefunc(&tmp, f);
bool ok = py_tpcall(tp_staticmethod, 1, &tmp);
if(!ok) {
py_printexc();
c11__abort("py_bindstaticmethod(): failed to create staticmethod");
}
py_setdict(py_tpobject(type), py_name(name), py_retval());
}
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f) {
py_TValue tmp;
py_newnativefunc(&tmp, f);
py_setdict(obj, py_name(name), &tmp);
}
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter) {
py_TValue tmp;
py_newobject(&tmp, tp_property, 2, 0);
py_newnativefunc(py_getslot(&tmp, 0), getter);
if(setter) {
py_newnativefunc(py_getslot(&tmp, 1), setter);
} else {
py_setslot(&tmp, 1, py_None());
}
py_setdict(py_tpobject(type), py_name(name), &tmp);
}
void py_bindmagic(py_Type type, py_Name name, py_CFunction f) {
py_Ref tmp = py_emplacedict(py_tpobject(type), name);
py_newnativefunc(tmp, f);
}
// src/public\CodeExecution.c
#include <assert.h>
#include <ctype.h>
py_Type pk_code__register() {
py_Type type = pk_newtype("code", tp_object, NULL, (py_Dtor)CodeObject__dtor, false, true);
return type;
}
static bool _py_compile(CodeObject* out,
const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic) {
VM* vm = pk_current_vm;
SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic);
Error* err = pk_compile(src, out);
if(err) {
py_exception(tp_SyntaxError, err->msg);
py_BaseException__stpush(NULL, &vm->unhandled_exc, err->src, err->lineno, NULL);
PK_DECREF(src);
PK_DECREF(err->src);
PK_FREE(err);
return false;
}
PK_DECREF(src);
return true;
}
bool pk_exec(CodeObject* co, py_Ref module) {
VM* vm = pk_current_vm;
if(!module) module = vm->main;
assert(module->type == tp_module);
py_StackRef sp = vm->stack.sp;
py_Frame* frame = Frame__new(co, sp, module, module, py_NIL(), true);
VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm);
if(res == RES_ERROR) return false;
assert(res == RES_RETURN);
return true;
}
bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals) {
VM* vm = pk_current_vm;
if(!module) module = vm->main;
assert(module->type == tp_module);
py_StackRef sp = vm->stack.sp;
assert(globals != NULL && locals != NULL);
// check globals
if(globals->type == tp_namedict) {
globals = py_getslot(globals, 0);
assert(globals->type == tp_module);
} else {
if(!py_istype(globals, tp_dict)) { return TypeError("globals must be a dict object"); }
}
// check locals
switch(locals->type) {
case tp_locals: break;
case tp_dict: break;
case tp_nil: break;
default: return TypeError("locals must be a dict object");
}
py_Frame* frame = Frame__new(co, sp, module, globals, locals, true);
VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm);
if(res == RES_ERROR) return false;
assert(res == RES_RETURN);
return true;
}
static bool
pk_smartexec(const char* source, py_Ref module, enum py_CompileMode mode, va_list args) {
if(module == NULL) module = pk_current_vm->main;
pk_mappingproxy__namedict(py_pushtmp(), module); // globals
py_newdict(py_pushtmp()); // locals
bool ok = py_compile(source, "<string>", mode, true);
if(!ok) return false;
py_push(py_retval());
// [globals, locals, code]
CodeObject* co = py_touserdata(py_peek(-1));
py_StackRef locals = py_peek(-2);
int max_index = -1;
c11__foreach(Bytecode, &co->codes, bc) {
if(bc->op == OP_LOAD_NAME) {
c11_sv name = py_name2sv(c11__getitem(py_Name, &co->names, bc->arg));
if(name.data[0] != '_') continue;
int index;
if(name.size == 1) {
index = 0;
} else if(name.size == 2 && isdigit(name.data[1])) {
index = name.data[1] - '0';
} else {
continue;
}
max_index = c11__max(max_index, index);
}
}
if(max_index == -1) return ValueError("no placeholder found in the source");
for(int i = 0; i <= max_index; i++) {
py_Ref val = va_arg(args, py_Ref);
char buf[3];
buf[0] = '_';
buf[1] = '0' + i;
buf[2] = '\0';
py_dict_setitem_by_str(locals, buf, val);
if(i == 0) {
// _ => _0
py_dict_setitem_by_str(locals, "_", val);
}
}
ok = pk_execdyn(co, module, py_peek(-3), locals);
if(!ok) return false;
py_shrink(3);
return true;
}
bool py_compile(const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic) {
CodeObject co;
bool ok = _py_compile(&co, source, filename, mode, is_dynamic);
if(ok) {
// compile success
CodeObject* ud = py_newobject(py_retval(), tp_code, 0, sizeof(CodeObject));
*ud = co;
}
return ok;
}
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
CodeObject co;
if(!_py_compile(&co, source, filename, mode, false)) return false;
bool ok = pk_exec(&co, module);
CodeObject__dtor(&co);
return ok;
}
bool py_execo(const void* data, int size, const char* filename, py_Ref module) {
CodeObject co;
char* err = CodeObject__loads(data, size, filename, &co);
if(err == NULL) {
c11__rtassert(co.src->mode == EXEC_MODE);
c11__rtassert(co.src->is_dynamic == false);
bool ok = pk_exec(&co, module);
CodeObject__dtor(&co);
return ok;
} else {
return RuntimeError("bad code object %s: %s", filename, err);
}
}
bool py_eval(const char* source, py_Ref module) {
return py_exec(source, "<string>", EVAL_MODE, module);
}
bool py_smartexec(const char* source, py_Ref module, ...) {
va_list args;
va_start(args, module);
bool ok = pk_smartexec(source, module, EXEC_MODE, args);
va_end(args);
return ok;
}
bool py_smarteval(const char* source, py_Ref module, ...) {
va_list args;
va_start(args, module);
bool ok = pk_smartexec(source, module, EVAL_MODE, args);
va_end(args);
return ok;
}
// src/public\DictSlots.c
PK_INLINE py_Ref py_getreg(int i) { return pk_current_vm->reg + i; }
PK_INLINE void py_setreg(int i, py_Ref val) { pk_current_vm->reg[i] = *val; }
PK_INLINE py_Ref py_retval() { return &pk_current_vm->last_retval; }
PK_INLINE py_Ref py_getdict(py_Ref self, py_Name name) {
assert(self && self->is_ptr);
return NameDict__try_get(PyObject__dict(self->_obj), name);
}
PK_INLINE void py_setdict(py_Ref self, py_Name name, py_Ref val) {
assert(self && self->is_ptr);
NameDict__set(PyObject__dict(self->_obj), name, val);
}
bool py_deldict(py_Ref self, py_Name name) {
assert(self && self->is_ptr);
return NameDict__del(PyObject__dict(self->_obj), name);
}
py_ItemRef py_emplacedict(py_Ref self, py_Name name) {
py_setdict(self, name, py_NIL());
return py_getdict(self, name);
}
bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) {
assert(self && self->is_ptr);
NameDict* dict = PyObject__dict(self->_obj);
for(int i = 0; i < dict->capacity; i++) {
NameDict_KV* kv = &dict->items[i];
if(kv->key == NULL) continue;
bool ok = f(kv->key, &kv->value, ctx);
if(!ok) return false;
}
return true;
}
void py_cleardict(py_Ref self) {
assert(self && self->is_ptr);
NameDict* dict = PyObject__dict(self->_obj);
NameDict__clear(dict);
}
py_Ref py_getslot(py_Ref self, int i) {
assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots);
return PyObject__slots(self->_obj) + i;
}
void py_setslot(py_Ref self, int i, py_Ref val) {
assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots);
PyObject__slots(self->_obj)[i] = *val;
}
py_Ref py_getbuiltin(py_Name name) { return py_getdict(pk_current_vm->builtins, name); }
py_Ref py_getglobal(py_Name name) { return py_getdict(pk_current_vm->main, name); }
void py_setglobal(py_Name name, py_Ref val) { py_setdict(pk_current_vm->main, name, val); }
// src/public\FrameOps.c
const char* py_Frame_sourceloc(py_Frame* self, int* lineno) {
SourceLocation loc = Frame__source_location(self);
*lineno = loc.lineno;
return loc.src->filename->data;
}
void py_Frame_newglobals(py_Frame* frame, py_OutRef out) {
if(!frame) {
pk_mappingproxy__namedict(out, pk_current_vm->main);
return;
}
if(frame->globals->type == tp_module) {
pk_mappingproxy__namedict(out, frame->globals);
} else {
*out = *frame->globals; // dict
}
}
void py_Frame_newlocals(py_Frame* frame, py_OutRef out) {
if(!frame) {
py_newdict(out);
return;
}
if(frame->is_locals_special) {
switch(frame->locals->type) {
case tp_locals: frame = frame->locals->_ptr; break;
case tp_dict: *out = *frame->locals; return;
case tp_nil: py_newdict(out); return;
default: c11__unreachable();
}
}
FastLocals__to_dict(frame->locals, frame->co);
py_assign(out, py_retval());
}
py_StackRef py_Frame_function(py_Frame* self) {
if(self->is_locals_special) return NULL;
assert(self->p0->type == tp_function);
return self->p0;
}
// src/public\GlobalSetup.c
_Thread_local VM* pk_current_vm;
static bool pk_initialized;
static bool pk_finalized;
static VM pk_default_vm;
static VM* pk_all_vm[16];
static py_TValue _True, _False, _None, _NIL;
void py_initialize() {
c11__rtassert(!pk_finalized);
if(pk_initialized) {
// c11__abort("py_initialize() can only be called once!");
return;
}
pk_names_initialize();
// check endianness
int x = 1;
bool is_little_endian = *(char*)&x == 1;
if(!is_little_endian) c11__abort("is_little_endian != true");
_Static_assert(sizeof(py_TValue) == 24, "sizeof(py_TValue) != 24");
_Static_assert(offsetof(py_TValue, extra) == 4, "offsetof(py_TValue, extra) != 4");
// check sizes
_Static_assert(sizeof(float) == 4, "");
_Static_assert(sizeof(double) == 8, "");
pk_current_vm = pk_all_vm[0] = &pk_default_vm;
// initialize some convenient references
py_newbool(&_True, true);
py_newbool(&_False, false);
py_newnone(&_None);
py_newnil(&_NIL);
VM__ctor(&pk_default_vm);
pk_initialized = true;
}
void py_finalize() {
if(pk_finalized) c11__abort("py_finalize() can only be called once!");
pk_finalized = true;
for(int i = 1; i < 16; i++) {
VM* vm = pk_all_vm[i];
if(vm) {
// temp fix https://github.com/pocketpy/pocketpy/issues/315
// TODO: refactor VM__ctor and VM__dtor
pk_current_vm = vm;
VM__dtor(vm);
PK_FREE(vm);
}
}
pk_current_vm = &pk_default_vm;
VM__dtor(&pk_default_vm);
pk_current_vm = NULL;
pk_names_finalize();
}
int VM__index(VM* self) {
for(int i = 0; i < 16; i++) {
if(pk_all_vm[i] == self) return i;
}
return -1;
}
int py_currentvm() { return VM__index(pk_current_vm); }
void py_switchvm(int index) {
if(index < 0 || index >= 16) c11__abort("invalid vm index");
if(!pk_all_vm[index]) {
pk_current_vm = pk_all_vm[index] = PK_MALLOC(sizeof(VM));
memset(pk_current_vm, 0, sizeof(VM));
VM__ctor(pk_all_vm[index]);
} else {
pk_current_vm = pk_all_vm[index];
}
}
void py_resetvm() {
VM* vm = pk_current_vm;
VM__dtor(vm);
memset(vm, 0, sizeof(VM));
VM__ctor(vm);
}
void py_resetallvm() {
for(int i = 0; i < 16; i++) {
py_switchvm(i);
py_resetvm();
}
py_switchvm(0);
}
void* py_getvmctx() { return pk_current_vm->ctx; }
void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
py_Callbacks* py_callbacks() { return &pk_current_vm->callbacks; }
py_AppCallbacks* py_appcallbacks() {
static py_AppCallbacks _callbacks = {0};
return &_callbacks;
}
/////////////////////////////
void py_sys_setargv(int argc, char** argv) {
py_GlobalRef sys = py_getmodule("sys");
py_Ref argv_list = py_getdict(sys, py_name("argv"));
py_list_clear(argv_list);
for(int i = 1; i < argc; i++) {
py_newstr(py_list_emplace(argv_list), argv[i]);
}
}
void py_sys_settrace(py_TraceFunc func, bool reset) {
TraceInfo* info = &pk_current_vm->trace_info;
info->func = func;
if(!reset) return;
if(info->prev_loc.src) {
PK_DECREF(info->prev_loc.src);
info->prev_loc.src = NULL;
}
info->prev_loc.lineno = -1;
}
int py_gc_collect() {
ManagedHeap* heap = &pk_current_vm->heap;
return ManagedHeap__collect(heap);
}
/////////////////////////////
void* py_malloc(size_t size) { return PK_MALLOC(size); }
void* py_realloc(void* ptr, size_t size) { return PK_REALLOC(ptr, size); }
void py_free(void* ptr) { PK_FREE(ptr); }
/////////////////////////////
py_GlobalRef py_True() { return &_True; }
py_GlobalRef py_False() { return &_False; }
py_GlobalRef py_None() { return &_None; }
py_GlobalRef py_NIL() { return &_NIL; }
/////////////////////////////
const char* pk_opname(Opcode op) {
const static char* OP_NAMES[] = {
#define OPCODE(name) #name,
#ifdef OPCODE
/**************************/
OPCODE(NO_OP)
/**************************/
OPCODE(POP_TOP)
OPCODE(DUP_TOP)
OPCODE(DUP_TOP_TWO)
OPCODE(ROT_TWO)
OPCODE(ROT_THREE)
OPCODE(PRINT_EXPR)
/**************************/
OPCODE(LOAD_CONST)
OPCODE(LOAD_NONE)
OPCODE(LOAD_TRUE)
OPCODE(LOAD_FALSE)
/**************************/
OPCODE(LOAD_SMALL_INT)
OPCODE(LOAD_NAME_AS_INT)
/**************************/
OPCODE(LOAD_ELLIPSIS)
OPCODE(LOAD_FUNCTION)
OPCODE(LOAD_NULL)
/**************************/
OPCODE(LOAD_FAST)
OPCODE(LOAD_NAME)
OPCODE(LOAD_NONLOCAL)
OPCODE(LOAD_GLOBAL)
OPCODE(LOAD_ATTR)
OPCODE(LOAD_CLASS_GLOBAL)
OPCODE(LOAD_METHOD)
OPCODE(LOAD_SUBSCR)
OPCODE(STORE_FAST)
OPCODE(STORE_NAME)
OPCODE(STORE_GLOBAL)
OPCODE(STORE_ATTR)
OPCODE(STORE_SUBSCR)
OPCODE(DELETE_FAST)
OPCODE(DELETE_NAME)
OPCODE(DELETE_GLOBAL)
OPCODE(DELETE_ATTR)
OPCODE(DELETE_SUBSCR)
/**************************/
OPCODE(BUILD_IMAG)
OPCODE(BUILD_BYTES)
OPCODE(BUILD_TUPLE)
OPCODE(BUILD_LIST)
OPCODE(BUILD_DICT)
OPCODE(BUILD_SET)
OPCODE(BUILD_SLICE)
OPCODE(BUILD_STRING)
/**************************/
OPCODE(BINARY_ADD)
OPCODE(BINARY_SUB)
OPCODE(BINARY_MUL)
OPCODE(BINARY_TRUEDIV)
OPCODE(BINARY_FLOORDIV)
OPCODE(BINARY_MOD)
OPCODE(BINARY_POW)
OPCODE(BINARY_LSHIFT)
OPCODE(BINARY_RSHIFT)
OPCODE(BINARY_AND)
OPCODE(BINARY_OR)
OPCODE(BINARY_XOR)
OPCODE(BINARY_MATMUL)
OPCODE(COMPARE_LT)
OPCODE(COMPARE_LE)
OPCODE(COMPARE_EQ)
OPCODE(COMPARE_NE)
OPCODE(COMPARE_GT)
OPCODE(COMPARE_GE)
OPCODE(IS_OP)
OPCODE(CONTAINS_OP)
/**************************/
OPCODE(JUMP_FORWARD)
OPCODE(POP_JUMP_IF_NOT_MATCH)
OPCODE(POP_JUMP_IF_FALSE)
OPCODE(POP_JUMP_IF_TRUE)
OPCODE(JUMP_IF_TRUE_OR_POP)
OPCODE(JUMP_IF_FALSE_OR_POP)
OPCODE(SHORTCUT_IF_FALSE_OR_POP)
OPCODE(LOOP_CONTINUE)
OPCODE(LOOP_BREAK)
/**************************/
OPCODE(CALL)
OPCODE(CALL_VARGS)
/**************************/
OPCODE(RETURN_VALUE)
OPCODE(YIELD_VALUE)
OPCODE(FOR_ITER_YIELD_VALUE)
/**************************/
OPCODE(LIST_APPEND)
OPCODE(DICT_ADD)
OPCODE(SET_ADD)
/**************************/
OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT)
OPCODE(UNARY_STAR)
OPCODE(UNARY_INVERT)
/**************************/
OPCODE(GET_ITER)
OPCODE(FOR_ITER)
/**************************/
OPCODE(IMPORT_PATH)
OPCODE(POP_IMPORT_STAR)
/**************************/
OPCODE(UNPACK_SEQUENCE)
OPCODE(UNPACK_EX)
/**************************/
OPCODE(BEGIN_CLASS)
OPCODE(END_CLASS)
OPCODE(STORE_CLASS_ATTR)
OPCODE(ADD_CLASS_ANNOTATION)
/**************************/
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
/**************************/
OPCODE(BEGIN_TRY)
OPCODE(END_TRY)
OPCODE(EXCEPTION_MATCH)
OPCODE(HANDLE_EXCEPTION)
OPCODE(RAISE)
OPCODE(RAISE_ASSERT)
OPCODE(RE_RAISE)
OPCODE(PUSH_EXCEPTION)
/**************************/
OPCODE(FORMAT_STRING)
/**************************/
#endif
#undef OPCODE
};
return OP_NAMES[op];
}
// src/public\Inspection.c
py_StackRef py_inspect_currentfunction() {
VM* vm = pk_current_vm;
if(vm->curr_function >= vm->stack.sp) return NULL;
return vm->curr_function;
}
py_GlobalRef py_inspect_currentmodule() {
py_Frame* frame = pk_current_vm->top_frame;
if(!frame) return NULL;
return frame->module;
}
py_Frame* py_inspect_currentframe() { return pk_current_vm->top_frame; }
void py_newglobals(py_OutRef out) {
py_Frame* frame = pk_current_vm->top_frame;
py_Frame_newglobals(frame, out);
}
void py_newlocals(py_OutRef out) {
py_Frame* frame = pk_current_vm->top_frame;
py_Frame_newlocals(frame, out);
}
// src/public\ModuleSystem.c
py_Ref py_getmodule(const char* path) {
VM* vm = pk_current_vm;
return BinTree__try_get(&vm->modules, (void*)path);
}
static py_Ref pk_newmodule(const char* path, bool is_init) {
c11_sv pathv = {path, strlen(path)};
if(pathv.size > PK_MAX_MODULE_PATH_LEN) c11__abort("module path too long: %s", path);
if(pathv.size == 0) c11__abort("module path cannot be empty");
py_ModuleInfo* mi = py_newobject(py_retval(), tp_module, -1, sizeof(py_ModuleInfo));
int last_dot = c11_sv__rindex(pathv, '.');
if(last_dot == -1 || is_init) {
mi->package = c11_string__new(path);
} else {
// a.b.c -> a.b
mi->package = c11_string__new2(path, last_dot);
}
mi->path = c11_string__new(path);
path = mi->path->data;
// we do not allow override in order to avoid memory leak
// it is because Module objects are not garbage collected
bool exists = BinTree__contains(&pk_current_vm->modules, (void*)path);
if(exists) c11__abort("module '%s' already exists", path);
BinTree__set(&pk_current_vm->modules, (void*)path, py_retval());
py_GlobalRef retval = py_getmodule(path);
mi->self = retval;
// setup __name__
py_newstrv(py_emplacedict(retval, __name__), c11_string__sv(mi->path));
// setup __package__
py_newstrv(py_emplacedict(retval, __package__), c11_string__sv(mi->package));
return retval;
}
py_Ref py_newmodule(const char* path) {
return pk_newmodule(path, false);
}
static void py_ModuleInfo__dtor(py_ModuleInfo* mi) {
c11_string__delete(mi->package);
c11_string__delete(mi->path);
}
py_Type pk_module__register() {
py_Type type = pk_newtype("module", tp_object, NULL, (py_Dtor)py_ModuleInfo__dtor, false, true);
return type;
}
int load_module_from_dll_desktop_only(const char* path) PY_RAISE PY_RETURN;
int py_import(const char* path_cstr) {
VM* vm = pk_current_vm;
c11_sv path = {path_cstr, strlen(path_cstr)};
if(path.size == 0) {
ValueError("empty module name");
return -1;
}
if(path.size > PK_MAX_MODULE_PATH_LEN) {
ValueError("module name too long: %v", path);
return -1;
}
if(path.data[0] == '.') {
c11__rtassert(vm->top_frame != NULL && vm->top_frame->module != NULL);
// try relative import
int dot_count = 1;
while(dot_count < path.size && path.data[dot_count] == '.')
dot_count++;
py_ModuleInfo* mi = py_touserdata(vm->top_frame->module);
c11_sv package_sv = c11_string__sv(mi->package);
if(package_sv.size == 0) {
ImportError("attempted relative import with no known parent package");
return -1;
}
c11_vector /* T=c11_sv */ cpnts = c11_sv__split(package_sv, '.');
for(int i = 1; i < dot_count; i++) {
if(cpnts.length == 0){
ImportError("attempted relative import beyond top-level package");
return -1;
}
c11_vector__pop(&cpnts);
}
if(dot_count < path.size) {
c11_sv last_cpnt = c11_sv__slice(path, dot_count);
c11_vector__push(c11_sv, &cpnts, last_cpnt);
}
// join cpnts
c11_sbuf buf;
c11_sbuf__ctor(&buf);
for(int i = 0; i < cpnts.length; i++) {
if(i > 0) c11_sbuf__write_char(&buf, '.');
c11_sbuf__write_sv(&buf, c11__getitem(c11_sv, &cpnts, i));
}
c11_vector__dtor(&cpnts);
c11_string* new_path = c11_sbuf__submit(&buf);
int res = py_import(new_path->data);
c11_string__delete(new_path);
return res;
}
c11__rtassert(path.data[0] != '.' && path.data[path.size - 1] != '.');
// import parent module (implicit recursion)
int last_dot_index = c11_sv__rindex(path, '.');
if(last_dot_index >= 0) {
c11_sv ppath = c11_sv__slice2(path, 0, last_dot_index);
py_GlobalRef ext_mod = py_getmodule(ppath.data);
if(!ext_mod) {
char buf[PK_MAX_MODULE_PATH_LEN + 1];
memcpy(buf, ppath.data, ppath.size);
buf[ppath.size] = '\0';
int res = py_import(buf);
if(res != 1) return res;
py_newnil(py_retval());
}
}
// check existing module
py_GlobalRef ext_mod = py_getmodule(path.data);
if(ext_mod) {
py_assign(py_retval(), ext_mod);
return 1;
}
if(vm->callbacks.lazyimport) {
py_GlobalRef lazymod = vm->callbacks.lazyimport(path_cstr);
if(lazymod) {
c11__rtassert(py_istype(lazymod, tp_module));
py_assign(py_retval(), lazymod);
return 1;
}
}
// try import
c11_string* slashed_path = c11_sv__replace(path, '.', PK_PLATFORM_SEP);
c11_string* filename = c11_string__new3("%s.py", slashed_path->data);
bool need_free = true;
bool is_pyc = false;
bool is_init = false;
const char* data = load_kPythonLib(path_cstr);
int data_size = -1;
if(data != NULL) {
need_free = false;
goto __SUCCESS;
}
data = vm->callbacks.importfile(filename->data, &data_size);
if(data != NULL) goto __SUCCESS;
c11_string__delete(filename);
filename = c11_string__new3("%s.pyc", slashed_path->data);
data = vm->callbacks.importfile(filename->data, &data_size);
if(data != NULL) {
is_pyc = true;
goto __SUCCESS;
}
c11_string__delete(filename);
filename = c11_string__new3("%s%c__init__.py", slashed_path->data, PK_PLATFORM_SEP);
data = vm->callbacks.importfile(filename->data, &data_size);
if(data != NULL) {
is_init = true;
goto __SUCCESS;
}
c11_string__delete(filename);
filename = c11_string__new3("%s%c__init__.pyc", slashed_path->data, PK_PLATFORM_SEP);
data = vm->callbacks.importfile(filename->data, &data_size);
if(data != NULL) {
is_pyc = true;
is_init = true;
goto __SUCCESS;
}
c11_string__delete(filename);
c11_string__delete(slashed_path);
// not found
return load_module_from_dll_desktop_only(path_cstr);
__SUCCESS:
do {
} while(0);
py_GlobalRef mod = pk_newmodule(path_cstr, is_init);
bool ok;
if(is_pyc) {
ok = py_execo(data, data_size, filename->data, mod);
} else {
ok = py_exec(data, filename->data, EXEC_MODE, mod);
}
py_assign(py_retval(), mod);
c11_string__delete(filename);
c11_string__delete(slashed_path);
if(need_free) PK_FREE((void*)data);
return ok ? 1 : -1;
}
bool py_importlib_reload(py_Ref module) {
VM* vm = pk_current_vm;
py_ModuleInfo* mi = py_touserdata(module);
// We should ensure that the module is its original py_GlobalRef
module = mi->self;
c11_sv path = c11_string__sv(mi->path);
c11_string* slashed_path = c11_sv__replace(path, '.', PK_PLATFORM_SEP);
c11_string* filename = c11_string__new3("%s.py", slashed_path->data);
// Here we only consider source modules.
// Because compiled modules have no source file (it cannot be reloaded)
char* data = vm->callbacks.importfile(filename->data, NULL);
if(data == NULL) {
c11_string__delete(filename);
filename = c11_string__new3("%s%c__init__.py", slashed_path->data, PK_PLATFORM_SEP);
data = vm->callbacks.importfile(filename->data, NULL);
}
c11_string__delete(slashed_path);
if(data == NULL) return ImportError("module '%v' not found", path);
// py_cleardict(module); BUG: removing old classes will cause RELOAD_MODE to fail
bool ok = py_exec(data, filename->data, RELOAD_MODE, module);
c11_string__delete(filename);
PK_FREE(data);
py_assign(py_retval(), module);
return ok;
}
// src/public\PyDict.c
typedef struct {
Dict* dict; // weakref for slot 0
Dict dict_backup;
DictEntry* curr;
DictEntry* end;
int mode; // 0: keys, 1: values, 2: items
} DictIterator;
#define Dict__step(x) ((x) < mask ? (x) + 1 : 0)
static uint32_t Dict__next_cap(uint32_t cap) {
switch(cap) {
case 7: return 17;
case 17: return 37;
case 37: return 79;
case 79: return 163;
case 163: return 331;
case 331: return 673;
case 673: return 1361;
case 1361: return 2053;
case 2053: return 3083;
case 3083: return 4637;
case 4637: return 6959;
case 6959: return 10453;
case 10453: return 15683;
case 15683: return 23531;
case 23531: return 35311;
case 35311: return 52967;
case 52967: return 79451;
case 79451: return 119179;
case 119179: return 178781;
case 178781: return 268189;
case 268189: return 402299;
case 402299: return 603457;
case 603457: return 905189;
case 905189: return 1357787;
case 1357787: return 2036687;
case 2036687: return 3055043;
case 3055043: return 4582577;
case 4582577: return 6873871;
case 6873871: return 10310819;
case 10310819: return 15466229;
case 15466229: return 23199347;
case 23199347: return 34799021;
case 34799021: return 52198537;
case 52198537: return 78297827;
case 78297827: return 117446801;
case 117446801: return 176170229;
case 176170229: return 264255353;
case 264255353: return 396383041;
case 396383041: return 594574583;
case 594574583: return 891861923;
default: c11__unreachable();
}
}
static uint64_t Dict__hash_2nd(uint64_t key) {
// https://gist.github.com/badboy/6267743
key = (~key) + (key << 21); // key = (key << 21) - key - 1
key = key ^ (key >> 24);
key = (key + (key << 3)) + (key << 8); // key * 265
key = key ^ (key >> 14);
key = (key + (key << 2)) + (key << 4); // key * 21
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}
static void Dict__ctor(Dict* self, uint32_t capacity, int entries_capacity) {
self->length = 0;
self->capacity = capacity;
size_t indices_size;
if(self->capacity < UINT16_MAX) {
self->index_is_short = true;
indices_size = self->capacity * sizeof(uint16_t);
self->null_index_value = UINT16_MAX;
} else {
self->index_is_short = false;
indices_size = self->capacity * sizeof(uint32_t);
self->null_index_value = UINT32_MAX;
}
self->indices = PK_MALLOC(indices_size);
memset(self->indices, -1, indices_size);
c11_vector__ctor(&self->entries, sizeof(DictEntry));
c11_vector__reserve(&self->entries, entries_capacity);
}
static void Dict__dtor(Dict* self) {
self->length = 0;
self->capacity = 0;
PK_FREE(self->indices);
c11_vector__dtor(&self->entries);
}
static uint32_t Dict__get_index(Dict* self, uint32_t index) {
if(self->index_is_short) {
uint16_t* indices = self->indices;
return indices[index];
} else {
uint32_t* indices = self->indices;
return indices[index];
}
}
static void Dict__swap_null_index(Dict* self, uint32_t pre_z, uint32_t z) {
if(self->index_is_short) {
uint16_t* indices = self->indices;
assert(indices[pre_z] == UINT16_MAX);
indices[pre_z] = indices[z];
indices[z] = UINT16_MAX;
} else {
uint32_t* indices = self->indices;
assert(indices[pre_z] == UINT32_MAX);
indices[pre_z] = indices[z];
indices[z] = UINT32_MAX;
}
}
static void Dict__set_index(Dict* self, uint32_t index, uint32_t value) {
if(self->index_is_short) {
uint16_t* indices = self->indices;
indices[index] = (uint16_t)value;
} else {
uint32_t* indices = self->indices;
indices[index] = value;
}
}
// Dict__probe won't raise exception for string keys
static bool Dict__probe(Dict* self,
py_TValue* key,
uint64_t* p_hash,
uint32_t* p_idx,
DictEntry** p_entry) {
if(py_isstr(key)) {
*p_hash = c11_sv__hash(py_tosv(key));
} else {
py_i64 h_user;
if(!py_hash(key, &h_user)) return false;
*p_hash = Dict__hash_2nd((uint64_t)h_user);
}
uint32_t mask = self->capacity - 1;
uint32_t idx = (*p_hash) % self->capacity;
while(true) {
uint32_t idx2 = Dict__get_index(self, idx);
if(idx2 == self->null_index_value) break;
DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
if(entry->hash == (*p_hash)) {
if(py_isstr(&entry->key) && py_isstr(key)) {
c11_sv lhs = py_tosv(&entry->key);
c11_sv rhs = py_tosv(key);
if(c11__sveq(lhs, rhs)) {
*p_idx = idx;
*p_entry = entry;
return true;
}
} else {
int res = py_equal(&entry->key, key);
if(res == 1) {
*p_idx = idx;
*p_entry = entry;
return true;
}
if(res == -1) return false; // error
}
}
// try next index
idx = Dict__step(idx);
}
// not found
*p_idx = idx;
*p_entry = NULL;
return true;
}
static bool Dict__try_get(Dict* self, py_TValue* key, DictEntry** out) {
uint64_t hash;
uint32_t idx;
return Dict__probe(self, key, &hash, &idx, out);
}
static void Dict__clear(Dict* self) {
size_t indices_size = self->index_is_short ? self->capacity * sizeof(uint16_t)
: self->capacity * sizeof(uint32_t);
memset(self->indices, -1, indices_size);
c11_vector__clear(&self->entries);
self->length = 0;
}
static void Dict__rehash_2x(Dict* self) {
Dict old_dict = *self;
uint32_t new_capacity = Dict__next_cap(old_dict.capacity);
uint32_t mask = new_capacity - 1;
// create a new dict with new capacity
Dict__ctor(self, new_capacity, old_dict.entries.capacity);
// move entries from old dict to new dict
for(int i = 0; i < old_dict.entries.length; i++) {
DictEntry* old_entry = c11__at(DictEntry, &old_dict.entries, i);
if(py_isnil(&old_entry->key)) continue; // skip deleted
uint32_t idx = old_entry->hash % new_capacity;
while(true) {
uint32_t idx2 = Dict__get_index(self, idx);
if(idx2 == self->null_index_value) {
c11_vector__push(DictEntry, &self->entries, *old_entry);
Dict__set_index(self, idx, self->entries.length - 1);
self->length++;
break;
}
// try next index
idx = Dict__step(idx);
}
}
Dict__dtor(&old_dict);
}
static void Dict__compact_entries(Dict* self) {
uint32_t* mappings = PK_MALLOC(self->entries.length * sizeof(uint32_t));
int n = 0;
for(int i = 0; i < self->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
mappings[i] = n;
if(i != n) {
DictEntry* new_entry = c11__at(DictEntry, &self->entries, n);
*new_entry = *entry;
}
n++;
}
self->entries.length = n;
// update indices
for(uint32_t idx = 0; idx < self->capacity; idx++) {
uint32_t idx2 = Dict__get_index(self, idx);
if(idx2 == self->null_index_value) continue;
Dict__set_index(self, idx, mappings[idx2]);
}
PK_FREE(mappings);
}
static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
uint64_t hash;
uint32_t idx;
DictEntry* entry;
if(!Dict__probe(self, key, &hash, &idx, &entry)) return false;
if(entry) {
// update existing entry
entry->val = *val;
return true;
}
// insert new entry
DictEntry* new_entry = c11_vector__emplace(&self->entries);
new_entry->hash = hash;
new_entry->key = *key;
new_entry->val = *val;
Dict__set_index(self, idx, self->entries.length - 1);
self->length++;
// check if we need to rehash
float load_factor = (float)self->length / self->capacity;
if(load_factor > (self->index_is_short ? 0.3f : 0.4f)) Dict__rehash_2x(self);
return true;
}
/// Delete an entry from the dict.
/// -1: error, 0: not found, 1: found and deleted
static int Dict__pop(Dict* self, py_Ref key) {
// Dict__log_index(self, "before pop");
uint64_t hash;
uint32_t idx;
DictEntry* entry;
if(!Dict__probe(self, key, &hash, &idx, &entry)) return -1;
if(!entry) return 0; // not found
// found the entry, delete and return it
py_assign(py_retval(), &entry->val);
Dict__set_index(self, idx, self->null_index_value);
py_newnil(&entry->key);
py_newnil(&entry->val);
self->length--;
/* tidy */
// https://github.com/OpenHFT/Chronicle-Map/blob/820573a68471509ffc1b0584454f4a67c0be1b84/src/main/java/net/openhft/chronicle/hash/impl/CompactOffHeapLinearHashTable.java#L156
uint32_t mask = self->capacity - 1;
uint32_t posToRemove = idx;
uint32_t posToShift = posToRemove;
// int probe_count = 0;
// int swap_count = 0;
while(true) {
posToShift = Dict__step(posToShift);
uint32_t idx_z = Dict__get_index(self, posToShift);
if(idx_z == self->null_index_value) break;
uint64_t hash_z = c11__at(DictEntry, &self->entries, idx_z)->hash;
uint32_t insertPos = (uint64_t)hash_z % self->capacity;
// the following condition essentially means circular permutations
// of three (r = posToRemove, s = posToShift, i = insertPos)
// positions are accepted:
// [...i..r...s.] or
// [...r..s...i.] or
// [...s..i...r.]
bool cond1 = insertPos <= posToRemove;
bool cond2 = posToRemove <= posToShift;
if((cond1 && cond2) ||
// chain wrapped around capacity
(posToShift < insertPos && (cond1 || cond2))) {
Dict__swap_null_index(self, posToRemove, posToShift);
posToRemove = posToShift;
// swap_count++;
}
// probe_count++;
}
// printf("Dict__pop: probe_count=%d, swap_count=%d\n", probe_count, swap_count);
// compact entries if necessary
if(self->entries.length > 16 && (self->length < self->entries.length >> 1)) {
Dict__compact_entries(self); // compact entries
}
// Dict__log_index(self, "after pop");
return 1;
}
static void DictIterator__ctor(DictIterator* self, Dict* dict, int mode) {
assert(mode >= 0 && mode <= 2);
self->dict = dict;
self->dict_backup = *dict; // backup the dict
self->curr = dict->entries.data;
self->end = self->curr + dict->entries.length;
self->mode = mode;
}
static DictEntry* DictIterator__next(DictIterator* self) {
DictEntry* retval;
do {
if(self->curr == self->end) return NULL;
retval = self->curr++;
} while(py_isnil(&retval->key));
return retval;
}
static bool DictIterator__modified(DictIterator* self) {
return memcmp(self->dict, &self->dict_backup, sizeof(Dict)) != 0;
}
///////////////////////////////
static bool dict__new__(int argc, py_Ref argv) {
py_Type cls = py_totype(argv);
int slots = cls == tp_dict ? 0 : -1;
Dict* ud = py_newobject(py_retval(), cls, slots, sizeof(Dict));
Dict__ctor(ud, 17, 4);
return true;
}
void py_newdict(py_OutRef out) {
Dict* ud = py_newobject(out, tp_dict, 0, sizeof(Dict));
Dict__ctor(ud, 17, 4);
}
static bool dict__init__(int argc, py_Ref argv) {
if(argc > 2) return TypeError("dict.__init__() takes at most 2 arguments (%d given)", argc);
if(argc == 1) {
py_newnone(py_retval());
return true;
}
assert(argc == 2);
py_TValue* p;
int length = pk_arrayview(py_arg(1), &p);
if(length == -1) { return TypeError("dict.__init__() expects a list or tuple"); }
Dict* self = py_touserdata(argv);
for(int i = 0; i < length; i++) {
py_Ref tuple = &p[i];
if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
return ValueError("dict.__init__() argument must be a list of tuple-2");
}
py_Ref key = py_tuple_getitem(tuple, 0);
py_Ref val = py_tuple_getitem(tuple, 1);
if(!Dict__set(self, key, val)) return false;
}
py_newnone(py_retval());
return true;
}
static bool dict__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
Dict* self = py_touserdata(argv);
DictEntry* entry;
if(!Dict__try_get(self, py_arg(1), &entry)) return false;
if(entry) {
*py_retval() = entry->val;
return true;
}
// try __missing__
py_Ref missing = py_tpfindmagic(argv->type, __missing__);
if(missing) return py_call(missing, argc, argv);
return KeyError(py_arg(1));
}
static bool dict__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
Dict* self = py_touserdata(argv);
bool ok = Dict__set(self, py_arg(1), py_arg(2));
if(ok) py_newnone(py_retval());
return ok;
}
static bool dict__delitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
Dict* self = py_touserdata(argv);
int res = Dict__pop(self, py_arg(1));
if(res == 1) {
py_newnone(py_retval());
return true;
}
if(res == 0) return KeyError(py_arg(1));
return false;
}
static bool dict__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
Dict* self = py_touserdata(argv);
DictEntry* entry;
if(!Dict__try_get(self, py_arg(1), &entry)) return false;
py_newbool(py_retval(), entry != NULL);
return true;
}
static bool dict__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
py_newint(py_retval(), self->length);
return true;
}
static bool dict__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, '{');
bool is_first = true;
for(int i = 0; i < self->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
if(!is_first) c11_sbuf__write_cstr(&buf, ", ");
if(!py_repr(&entry->key)) return false;
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
c11_sbuf__write_cstr(&buf, ": ");
if(!py_repr(&entry->val)) return false;
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
is_first = false;
}
c11_sbuf__write_char(&buf, '}');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool dict__eq__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
Dict* self = py_touserdata(py_arg(0));
if(!py_isdict(py_arg(1))) {
py_newnotimplemented(py_retval());
return true;
}
Dict* other = py_touserdata(py_arg(1));
if(self->length != other->length) {
py_newbool(py_retval(), false);
return true;
}
DictIterator iter;
DictIterator__ctor(&iter, self, 2);
// for each self key
while(1) {
DictEntry* entry = DictIterator__next(&iter);
if(!entry) break;
DictEntry* other_entry;
if(!Dict__try_get(other, &entry->key, &other_entry)) return false;
if(!other_entry) {
py_newbool(py_retval(), false);
return true;
}
if(entry->hash != other_entry->hash) {
py_newbool(py_retval(), false);
return true;
}
int res = py_equal(&entry->val, &other_entry->val);
if(res == 0) {
py_newbool(py_retval(), false);
return true;
}
if(res == -1) return false; // error
}
py_newbool(py_retval(), true);
return true;
}
static bool dict__ne__(int argc, py_Ref argv) {
if(!dict__eq__(argc, argv)) return false;
if(py_isbool(py_retval())) {
bool res = py_tobool(py_retval());
py_newbool(py_retval(), !res);
}
return true;
}
static bool dict_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
Dict__clear(self);
py_newnone(py_retval());
return true;
}
static bool dict_copy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
Dict* new_dict = py_newobject(py_retval(), tp_dict, 0, sizeof(Dict));
new_dict->length = self->length;
new_dict->capacity = self->capacity;
new_dict->null_index_value = self->null_index_value;
new_dict->index_is_short = self->index_is_short;
// copy entries
new_dict->entries = c11_vector__copy(&self->entries);
// copy indices
size_t indices_size = self->index_is_short ? self->capacity * sizeof(uint16_t)
: self->capacity * sizeof(uint32_t);
new_dict->indices = PK_MALLOC(indices_size);
memcpy(new_dict->indices, self->indices, indices_size);
return true;
}
static bool dict_update(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_dict);
Dict* self = py_touserdata(argv);
Dict* other = py_touserdata(py_arg(1));
for(int i = 0; i < other->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &other->entries, i);
if(py_isnil(&entry->key)) continue;
if(!Dict__set(self, &entry->key, &entry->val)) return false;
}
py_newnone(py_retval());
return true;
}
static bool dict_get(int argc, py_Ref argv) {
Dict* self = py_touserdata(argv);
if(argc > 3) return TypeError("get() takes at most 3 arguments (%d given)", argc);
py_Ref default_val = argc == 3 ? py_arg(2) : py_None();
DictEntry* entry;
if(!Dict__try_get(self, py_arg(1), &entry)) return false;
*py_retval() = entry ? entry->val : *default_val;
return true;
}
static bool dict_pop(int argc, py_Ref argv) {
Dict* self = py_touserdata(argv);
if(argc < 2 || argc > 3) return TypeError("pop() takes 1 or 2 arguments (%d given)", argc - 1);
py_Ref default_val = argc == 3 ? py_arg(2) : py_None();
int res = Dict__pop(self, py_arg(1));
if(res == -1) return false;
if(res == 0) py_assign(py_retval(), default_val);
return true;
}
static bool dict_popitem(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
for(int i = self->entries.length - 1; i >= 0; i--) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
py_Ref p = py_newtuple(py_pushtmp(), 2);
p[0] = entry->key;
p[1] = entry->val;
int res = Dict__pop(self, &p[0]);
c11__rtassert(res == 1);
py_assign(py_retval(), py_peek(-1));
py_pop();
return true;
}
return KeyError(py_None());
}
static bool dict_keys(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
DictIterator* ud = py_newobject(py_retval(), tp_dict_iterator, 1, sizeof(DictIterator));
DictIterator__ctor(ud, self, 0);
py_setslot(py_retval(), 0, argv); // keep a reference to the dict
return true;
}
static bool dict_values(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
DictIterator* ud = py_newobject(py_retval(), tp_dict_iterator, 1, sizeof(DictIterator));
DictIterator__ctor(ud, self, 1);
py_setslot(py_retval(), 0, argv); // keep a reference to the dict
return true;
}
static bool dict_items(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv);
DictIterator* ud = py_newobject(py_retval(), tp_dict_iterator, 1, sizeof(DictIterator));
DictIterator__ctor(ud, self, 2);
py_setslot(py_retval(), 0, argv); // keep a reference to the dict
return true;
}
py_Type pk_dict__register() {
py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false);
py_bindmagic(type, __new__, dict__new__);
py_bindmagic(type, __init__, dict__init__);
py_bindmagic(type, __getitem__, dict__getitem__);
py_bindmagic(type, __setitem__, dict__setitem__);
py_bindmagic(type, __delitem__, dict__delitem__);
py_bindmagic(type, __contains__, dict__contains__);
py_bindmagic(type, __len__, dict__len__);
py_bindmagic(type, __repr__, dict__repr__);
py_bindmagic(type, __eq__, dict__eq__);
py_bindmagic(type, __ne__, dict__ne__);
py_bindmagic(type, __iter__, dict_keys);
py_bindmethod(type, "clear", dict_clear);
py_bindmethod(type, "copy", dict_copy);
py_bindmethod(type, "update", dict_update);
py_bindmethod(type, "get", dict_get);
py_bindmethod(type, "pop", dict_pop);
py_bindmethod(type, "popitem", dict_popitem);
py_bindmethod(type, "keys", dict_keys);
py_bindmethod(type, "values", dict_values);
py_bindmethod(type, "items", dict_items);
py_setdict(py_tpobject(type), __hash__, py_None());
return type;
}
//////////////////////////
bool dict_items__next__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
DictIterator* iter = py_touserdata(py_arg(0));
if(DictIterator__modified(iter)) return RuntimeError("dictionary modified during iteration");
DictEntry* entry = (DictIterator__next(iter));
if(entry) {
switch(iter->mode) {
case 0: // keys
py_assign(py_retval(), &entry->key);
return true;
case 1: // values
py_assign(py_retval(), &entry->val);
return true;
case 2: // items
{
py_Ref p = py_newtuple(py_retval(), 2);
p[0] = entry->key;
p[1] = entry->val;
return true;
}
default: c11__unreachable();
}
}
return StopIteration();
}
bool dict_items__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
DictIterator* iter = py_touserdata(py_arg(0));
py_newint(py_retval(), iter->dict->length);
return true;
}
py_Type pk_dict_items__register() {
py_Type type = pk_newtype("dict_iterator", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, dict_items__next__);
py_bindmagic(type, __len__, dict_items__len__);
return type;
}
//////////////////////////
int py_dict_getitem(py_Ref self, py_Ref key) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
DictEntry* entry;
if(!Dict__try_get(ud, key, &entry)) return -1;
if(entry) {
py_assign(py_retval(), &entry->val);
return 1;
}
return 0;
}
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
return Dict__set(ud, key, val);
}
int py_dict_delitem(py_Ref self, py_Ref key) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
return Dict__pop(ud, key);
}
int py_dict_getitem_by_str(py_Ref self, const char* key) {
py_Ref tmp = py_pushtmp();
py_newstr(tmp, key);
int res = py_dict_getitem(self, tmp);
py_pop();
return res;
}
bool py_dict_setitem_by_str(py_Ref self, const char* key, py_Ref val) {
py_Ref tmp = py_pushtmp();
py_newstr(tmp, key);
bool res = py_dict_setitem(self, tmp, val);
py_pop();
return res;
}
int py_dict_delitem_by_str(py_Ref self, const char* key) {
py_Ref tmp = py_pushtmp();
py_newstr(tmp, key);
int res = py_dict_delitem(self, tmp);
py_pop();
return res;
}
int py_dict_getitem_by_int(py_Ref self, py_i64 key) {
py_TValue tmp;
py_newint(&tmp, key);
return py_dict_getitem(self, &tmp);
}
bool py_dict_setitem_by_int(py_Ref self, py_i64 key, py_Ref val) {
py_TValue tmp;
py_newint(&tmp, key);
return py_dict_setitem(self, &tmp, val);
}
int py_dict_delitem_by_int(py_Ref self, py_i64 key) {
py_TValue tmp;
py_newint(&tmp, key);
return py_dict_delitem(self, &tmp);
}
int py_dict_len(py_Ref self) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
return ud->length;
}
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
Dict* ud = py_touserdata(self);
for(int i = 0; i < ud->entries.length; i++) {
DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
if(py_isnil(&entry->key)) continue;
if(!f(&entry->key, &entry->val, ctx)) return false;
}
return true;
}
#undef Dict__step
// src/public\PyException.c
void py_BaseException__stpush(py_Frame* frame,
py_Ref self,
SourceData_ src,
int lineno,
const char* func_name) {
BaseException* ud = py_touserdata(self);
int max_frame_dumps = py_debugger_status() == 1 ? 31 : 7;
if(ud->stacktrace.length >= max_frame_dumps) return;
BaseExceptionFrame* frame_dump = c11_vector__emplace(&ud->stacktrace);
PK_INCREF(src);
frame_dump->src = src;
frame_dump->lineno = lineno;
frame_dump->name = func_name ? c11_string__new(func_name) : NULL;
if(py_debugger_status() == 1) {
if(frame != NULL) {
py_Frame_newlocals(frame, &frame_dump->locals);
py_Frame_newglobals(frame, &frame_dump->globals);
} else {
py_newdict(&frame_dump->locals);
py_newdict(&frame_dump->globals);
}
}
}
static void BaseException__dtor(void* ud) {
BaseException* self = (BaseException*)ud;
c11__foreach(BaseExceptionFrame, &self->stacktrace, it) {
PK_DECREF(it->src);
if(it->name) c11_string__delete(it->name);
}
c11_vector__dtor(&self->stacktrace);
}
static bool _py_BaseException__new__(int argc, py_Ref argv) {
py_Type cls = py_totype(argv);
BaseException* ud = py_newobject(py_retval(), cls, 0, sizeof(BaseException));
py_newnil(&ud->args);
py_newnil(&ud->inner_exc);
c11_vector__ctor(&ud->stacktrace, sizeof(BaseExceptionFrame));
return true;
}
static bool _py_BaseException__init__(int argc, py_Ref argv) {
BaseException* ud = py_touserdata(argv);
py_newnone(py_retval());
if(argc == 1 + 0) return true;
if(argc == 1 + 1) {
py_assign(&ud->args, &argv[1]);
return true;
}
return TypeError("__init__() takes at most 1 arguments but %d were given", argc - 1);
}
static bool _py_BaseException__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
BaseException* ud = py_touserdata(argv);
c11_sbuf ss;
c11_sbuf__ctor(&ss);
pk_sprintf(&ss, "%t(", argv->type);
py_Ref args = &ud->args;
if(!py_isnil(args)) {
if(!py_repr(args)) return false;
c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
}
c11_sbuf__write_char(&ss, ')');
c11_sbuf__py_submit(&ss, py_retval());
return true;
}
static bool _py_BaseException__str__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
BaseException* ud = py_touserdata(argv);
c11_sbuf ss;
c11_sbuf__ctor(&ss);
py_Ref args = &ud->args;
if(!py_isnil(args)) {
if(argv->type == tp_KeyError) {
if(!py_repr(args)) return false;
} else {
if(!py_str(args)) return false;
}
c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
}
c11_sbuf__py_submit(&ss, py_retval());
return true;
}
static bool BaseException_args(int argc, py_Ref argv) {
BaseException* ud = py_touserdata(argv);
PY_CHECK_ARGC(1);
py_Ref args = &ud->args;
if(!py_isnil(args)) {
py_Ref p = py_newtuple(py_retval(), 1);
p[0] = *args;
} else {
py_newtuple(py_retval(), 0);
}
return true;
}
static bool StopIteration_value(int argc, py_Ref argv) {
BaseException* ud = py_touserdata(argv);
PY_CHECK_ARGC(1);
py_Ref args = &ud->args;
if(py_isnil(args)) {
py_newnone(py_retval());
} else {
py_assign(py_retval(), args);
}
return true;
}
py_Type pk_BaseException__register() {
py_Type type = pk_newtype("BaseException", tp_object, NULL, BaseException__dtor, false, false);
py_bindmagic(type, __new__, _py_BaseException__new__);
py_bindmagic(type, __init__, _py_BaseException__init__);
py_bindmagic(type, __repr__, _py_BaseException__repr__);
py_bindmagic(type, __str__, _py_BaseException__str__);
py_bindproperty(type, "args", BaseException_args, NULL);
return type;
}
py_Type pk_Exception__register() {
py_Type type = pk_newtype("Exception", tp_BaseException, NULL, NULL, false, false);
return type;
}
py_Type pk_StopIteration__register() {
py_Type type = pk_newtype("StopIteration", tp_Exception, NULL, NULL, false, false);
py_bindproperty(type, "value", StopIteration_value, NULL);
return type;
}
static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
c11_sbuf__write_cstr(self, "Traceback (most recent call last):\n");
BaseException* ud = py_touserdata(exc);
for(int i = ud->stacktrace.length - 1; i >= 0; i--) {
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
SourceData__snapshot(frame->src,
self,
frame->lineno,
NULL,
frame->name ? frame->name->data : NULL);
c11_sbuf__write_char(self, '\n');
}
const char* name = py_tpname(exc->type);
char* message = safe_stringify_exception(exc);
c11_sbuf__write_cstr(self, name);
c11_sbuf__write_cstr(self, ": ");
c11_sbuf__write_cstr(self, message);
PK_FREE(message);
}
char* safe_stringify_exception(py_Ref exc) {
VM* vm = pk_current_vm;
const char* message = "<exception str() failed>";
py_Ref tmp = py_pushtmp();
py_Ref old_unhandled_exc = py_pushtmp();
*tmp = *exc;
*old_unhandled_exc = vm->unhandled_exc;
py_newnil(&vm->unhandled_exc);
py_StackRef p0 = py_peek(0);
bool ok = py_str(tmp);
if(ok) {
if(py_isstr(py_retval())) message = py_tostr(py_retval());
} else {
py_clearexc(p0);
}
vm->unhandled_exc = *old_unhandled_exc;
py_shrink(2);
return c11_strdup(message);
}
//////////////////////////////////////////////////
bool py_checkexc() {
VM* vm = pk_current_vm;
return !py_isnil(&vm->unhandled_exc);
}
bool py_matchexc(py_Type type) {
VM* vm = pk_current_vm;
if(py_isnil(&vm->unhandled_exc)) return false;
bool ok = py_issubclass(vm->unhandled_exc.type, type);
if(ok) vm->last_retval = vm->unhandled_exc;
return ok;
}
void py_clearexc(py_StackRef p0) {
VM* vm = pk_current_vm;
py_newnil(&vm->unhandled_exc);
if(p0) {
c11__rtassert(p0 >= vm->stack.begin && p0 <= vm->stack.sp);
vm->stack.sp = p0;
}
}
void py_printexc() {
char* msg = py_formatexc();
if(!msg) return;
pk_current_vm->callbacks.print(msg);
pk_current_vm->callbacks.print("\n");
PK_FREE(msg);
}
char* py_formatexc() {
VM* vm = pk_current_vm;
if(py_isnil(&vm->unhandled_exc)) return NULL;
char* res = formatexc_internal(&vm->unhandled_exc);
if(py_debugger_status() == 1) py_debugger_exceptionbreakpoint(&vm->unhandled_exc);
return res;
}
char* formatexc_internal(py_Ref exc) {
c11__rtassert(exc != NULL);
c11__rtassert(py_issubclass(exc->type, tp_BaseException));
c11_sbuf ss;
c11_sbuf__ctor(&ss);
BaseException* ud = py_touserdata(exc);
py_Ref inner = &ud->inner_exc;
if(py_isnil(inner)) {
c11_sbuf__write_exc(&ss, exc);
} else {
c11_sbuf__write_exc(&ss, inner);
c11_sbuf__write_cstr(
&ss,
"\n\nDuring handling of the above exception, another exception occurred:\n\n");
c11_sbuf__write_exc(&ss, exc);
}
c11_string* res = c11_sbuf__submit(&ss);
char* dup = PK_MALLOC(res->size + 1);
memcpy(dup, res->data, res->size);
dup[res->size] = '\0';
c11_string__delete(res);
return dup;
}
bool py_exception(py_Type type, const char* fmt, ...) {
#ifndef NDEBUG
if(py_checkexc()) {
const char* name = py_tpname(pk_current_vm->unhandled_exc.type);
c11__abort("py_exception(): `%s` was already set!", name);
}
#endif
c11_sbuf buf;
c11_sbuf__ctor(&buf);
va_list args;
va_start(args, fmt);
pk_vsprintf(&buf, fmt, args);
va_end(args);
py_Ref message = py_pushtmp();
c11_sbuf__py_submit(&buf, message);
bool ok = py_tpcall(type, 1, message);
if(!ok) return false;
py_pop();
return py_raise(py_retval());
}
bool py_raise(py_Ref exc) {
assert(py_isinstance(exc, tp_BaseException));
VM* vm = pk_current_vm;
if(vm->top_frame) {
FrameExcInfo* info = Frame__top_exc_info(vm->top_frame);
if(info && !py_isnil(&info->exc)) {
BaseException* ud = py_touserdata(exc);
ud->inner_exc = info->exc;
}
}
assert(py_isnil(&vm->unhandled_exc));
vm->unhandled_exc = *exc;
return false;
}
bool KeyError(py_Ref key) {
bool ok = py_tpcall(tp_KeyError, 1, key);
if(!ok) return false;
return py_raise(py_retval());
}
bool StopIteration() {
bool ok = py_tpcall(tp_StopIteration, 0, NULL);
if(!ok) return false;
return py_raise(py_retval());
}
// src/public\PyList.c
void py_newlist(py_OutRef out) {
List* ud = py_newobject(out, tp_list, 0, sizeof(List));
c11_vector__ctor(ud, sizeof(py_TValue));
}
void py_newlistn(py_OutRef out, int n) {
py_newlist(out);
List* ud = py_touserdata(out);
c11_vector__reserve(ud, n);
ud->length = n;
}
py_Ref py_list_data(py_Ref self) {
List* ud = py_touserdata(self);
return ud->data;
}
py_Ref py_list_getitem(py_Ref self, int i) {
List* ud = py_touserdata(self);
return c11__at(py_TValue, ud, i);
}
void py_list_setitem(py_Ref self, int i, py_Ref val) {
List* ud = py_touserdata(self);
c11__setitem(py_TValue, ud, i, *val);
}
void py_list_delitem(py_Ref self, int i) {
List* ud = py_touserdata(self);
c11_vector__erase(py_TValue, ud, i);
}
int py_list_len(py_Ref self) {
List* ud = py_touserdata(self);
return ud->length;
}
void py_list_swap(py_Ref self, int i, int j) {
py_TValue* data = py_list_data(self);
py_TValue tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
void py_list_append(py_Ref self, py_Ref val) {
List* ud = py_touserdata(self);
c11_vector__push(py_TValue, ud, *val);
}
py_ItemRef py_list_emplace(py_Ref self) {
List* ud = py_touserdata(self);
c11_vector__emplace(ud);
return &c11_vector__back(py_TValue, ud);
}
void py_list_clear(py_Ref self) {
List* ud = py_touserdata(self);
c11_vector__clear(ud);
}
void py_list_insert(py_Ref self, int i, py_Ref val) {
List* ud = py_touserdata(self);
c11_vector__insert(py_TValue, ud, i, *val);
}
////////////////////////////////
static bool list__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_i64 res = py_list_len(py_arg(0));
py_newint(py_retval(), res);
return true;
}
static bool list__eq__(int argc, py_Ref argv) {
return pk_wrapper__arrayequal(tp_list, argc, argv);
}
static bool list__ne__(int argc, py_Ref argv) {
if(!list__eq__(argc, argv)) return false;
if(py_isbool(py_retval())) {
bool res = py_tobool(py_retval());
py_newbool(py_retval(), !res);
}
return true;
}
static bool list__new__(int argc, py_Ref argv) {
if(argc == 1) {
py_newlist(py_retval());
return true;
}
if(argc == 2) {
py_TValue* p;
int length = pk_arrayview(py_arg(1), &p);
if(length != -1) {
py_newlistn(py_retval(), length);
for(int i = 0; i < length; i++) {
py_list_setitem(py_retval(), i, p + i);
}
return true;
}
if(!py_iter(py_arg(1))) return false;
py_Ref iter = py_pushtmp();
py_Ref list = py_pushtmp();
*iter = *py_retval();
py_newlist(list);
while(true) {
int res = py_next(iter);
if(res == -1) {
py_shrink(2);
return false;
}
if(!res) break;
py_list_append(list, py_retval());
}
*py_retval() = *list;
py_shrink(2);
return true;
}
return TypeError("list() takes at most 1 argument");
}
static bool list__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0));
py_Ref _1 = py_arg(1);
if(_1->type == tp_int) {
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self->length)) return false;
*py_retval() = c11__getitem(py_TValue, self, index);
return true;
} else if(_1->type == tp_slice) {
int start, stop, step;
bool ok = pk__parse_int_slice(_1, self->length, &start, &stop, &step);
if(!ok) return false;
py_newlist(py_retval());
List* list = py_touserdata(py_retval());
PK_SLICE_LOOP(i, start, stop, step) {
c11_vector__push(py_TValue, list, c11__getitem(py_TValue, self, i));
}
return true;
} else {
return TypeError("list indices must be integers");
}
}
static bool list__setitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_int);
List* self = py_touserdata(py_arg(0));
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self->length)) return false;
c11__setitem(py_TValue, self, index, *py_arg(2));
py_newnone(py_retval());
return true;
}
static bool list__delitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0));
if(py_istype(py_arg(1), tp_slice)) {
int start, stop, step;
bool ok = pk__parse_int_slice(py_arg(1), self->length, &start, &stop, &step);
if(!ok) return false;
if(step != 1) return ValueError("slice step must be 1 for deletion");
int n = stop - start;
if(n > 0) {
py_TValue* p = self->data;
for(int i = stop; i < self->length; i++) {
p[start + i - stop] = p[i];
}
self->length -= n;
}
py_newnone(py_retval());
return true;
}
PY_CHECK_ARG_TYPE(1, tp_int);
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self->length)) return false;
c11_vector__erase(py_TValue, self, index);
py_newnone(py_retval());
return true;
}
static bool list__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_Ref _0 = py_arg(0);
py_Ref _1 = py_arg(1);
if(py_istype(_1, tp_list)) {
List* list_0 = py_touserdata(_0);
List* list_1 = py_touserdata(_1);
py_newlist(py_retval());
List* list = py_touserdata(py_retval());
c11_vector__extend(list, list_0->data, list_0->length);
c11_vector__extend(list, list_1->data, list_1->length);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool list__mul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_Ref _0 = py_arg(0);
py_Ref _1 = py_arg(1);
if(py_istype(_1, tp_int)) {
int n = py_toint(_1);
py_newlist(py_retval());
List* list = py_touserdata(py_retval());
List* list_0 = py_touserdata(_0);
for(int i = 0; i < n; i++) {
c11_vector__extend(list, list_0->data, list_0->length);
}
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool list__rmul__(int argc, py_Ref argv) { return list__mul__(argc, argv); }
static bool list_append(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_list_append(py_arg(0), py_arg(1));
py_newnone(py_retval());
return true;
}
static bool list__repr__(int argc, py_Ref argv) {
List* self = py_touserdata(py_arg(0));
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, '[');
for(int i = 0; i < self->length; i++) {
py_TValue* val = c11__at(py_TValue, self, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
if(i != self->length - 1) c11_sbuf__write_cstr(&buf, ", ");
}
c11_sbuf__write_char(&buf, ']');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool list_extend(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0));
py_TValue* p;
int length = pk_arrayview(py_arg(1), &p);
if(length >= 0) {
c11_vector__extend(self, p, length);
} else {
// get iterator
if (!py_iter(py_arg(1))) return false;
py_StackRef tmp_iter = py_pushtmp();
py_assign(tmp_iter, py_retval());
while(true) {
int res = py_next(tmp_iter);
if (res == 0) break;
if (res == -1) return false;
assert(res == 1);
c11_vector__push(py_TValue, self, *py_retval());
}
py_pop();
}
py_newnone(py_retval());
return true;
}
static bool list_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
int count = 0;
for(int i = 0; i < py_list_len(py_arg(0)); i++) {
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false;
if(res) count++;
}
py_newint(py_retval(), count);
return true;
}
static bool list_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_list_clear(py_arg(0));
py_newnone(py_retval());
return true;
}
static bool list_copy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_newlist(py_retval());
List* self = py_touserdata(py_arg(0));
List* list = py_touserdata(py_retval());
c11_vector__extend(list, self->data, self->length);
return true;
}
static bool list_index(int argc, py_Ref argv) {
if(argc > 3) return TypeError("index() takes at most 3 arguments");
int start = 0;
if(argc == 3) {
PY_CHECK_ARG_TYPE(2, tp_int);
start = py_toint(py_arg(2));
if(start < 0) start += py_list_len(py_arg(0));
if(start < 0) start = 0;
}
for(int i = start; i < py_list_len(py_arg(0)); i++) {
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false;
if(res) {
py_newint(py_retval(), i);
return true;
}
}
return ValueError("list.index(x): x not in list");
}
static bool list_reverse(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
List* self = py_touserdata(py_arg(0));
c11__reverse(py_TValue, self);
py_newnone(py_retval());
return true;
}
static bool list_remove(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
for(int i = 0; i < py_list_len(py_arg(0)); i++) {
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false;
if(res) {
py_list_delitem(py_arg(0), i);
py_newnone(py_retval());
return true;
}
}
return ValueError("list.remove(x): x not in list");
}
static bool list_pop(int argc, py_Ref argv) {
int index;
if(argc == 1) {
index = -1;
} else if(argc == 2) {
PY_CHECK_ARG_TYPE(1, tp_int);
index = py_toint(py_arg(1));
} else {
return TypeError("pop() takes at most 2 arguments");
}
List* self = py_touserdata(py_arg(0));
if(self->length == 0) return IndexError("pop from empty list");
if(!pk__normalize_index(&index, self->length)) return false;
*py_retval() = c11__getitem(py_TValue, self, index);
c11_vector__erase(py_TValue, self, index);
return true;
}
static bool list_insert(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_int);
List* self = py_touserdata(py_arg(0));
int index = py_toint(py_arg(1));
if(index < 0) index += self->length;
if(index < 0) index = 0;
if(index > self->length) index = self->length;
c11_vector__insert(py_TValue, self, index, *py_arg(2));
py_newnone(py_retval());
return true;
}
static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
if(!key) return py_less(a, b);
VM* vm = pk_current_vm;
// project a
py_push(key);
py_pushnil();
py_push(a);
if(!py_vectorcall(1, 0)) return -1;
py_push(py_retval());
// project b
py_push(key);
py_pushnil();
py_push(b);
if(!py_vectorcall(1, 0)) return -1;
py_push(py_retval());
// binary op
bool ok = pk_stack_binaryop(vm, __lt__, __gt__);
if(!ok) return -1;
py_shrink(2);
return py_bool(py_retval());
}
// sort(self, key=None, reverse=False)
static bool list_sort(int argc, py_Ref argv) {
List* self = py_touserdata(py_arg(0));
py_Ref key = py_arg(1);
if(py_isnone(key)) key = NULL;
bool ok = c11__stable_sort(self->data,
self->length,
sizeof(py_TValue),
(int (*)(const void*, const void*, void*))lt_with_key,
key);
if(!ok) return false;
PY_CHECK_ARG_TYPE(2, tp_bool);
bool reverse = py_tobool(py_arg(2));
if(reverse) c11__reverse(py_TValue, self);
py_newnone(py_retval());
return true;
}
static bool list__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
list_iterator* ud = py_newobject(py_retval(), tp_list_iterator, 1, sizeof(list_iterator));
ud->vec = py_touserdata(argv);
ud->index = 0;
py_setslot(py_retval(), 0, argv); // keep a reference to the object
return true;
}
static bool list__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
return pk_arraycontains(py_arg(0), py_arg(1));
}
py_Type pk_list__register() {
py_Type type =
pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true);
py_bindmagic(type, __len__, list__len__);
py_bindmagic(type, __eq__, list__eq__);
py_bindmagic(type, __ne__, list__ne__);
py_bindmagic(type, __new__, list__new__);
py_bindmagic(type, __getitem__, list__getitem__);
py_bindmagic(type, __setitem__, list__setitem__);
py_bindmagic(type, __delitem__, list__delitem__);
py_bindmagic(type, __add__, list__add__);
py_bindmagic(type, __mul__, list__mul__);
py_bindmagic(type, __rmul__, list__rmul__);
py_bindmagic(type, __repr__, list__repr__);
py_bindmagic(type, __iter__, list__iter__);
py_bindmagic(type, __contains__, list__contains__);
py_bindmethod(type, "append", list_append);
py_bindmethod(type, "extend", list_extend);
py_bindmethod(type, "count", list_count);
py_bindmethod(type, "clear", list_clear);
py_bindmethod(type, "copy", list_copy);
py_bindmethod(type, "index", list_index);
py_bindmethod(type, "reverse", list_reverse);
py_bindmethod(type, "remove", list_remove);
py_bindmethod(type, "pop", list_pop);
py_bindmethod(type, "insert", list_insert);
py_bindmethod(type, "sort", list_sort);
py_bind(py_tpobject(type), "sort(self, key=None, reverse=False)", list_sort);
py_setdict(py_tpobject(type), __hash__, py_None());
return type;
}
// src/public\PySlice.c
py_ObjectRef py_newslice(py_OutRef out) {
VM* vm = pk_current_vm;
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
out->type = tp_slice;
out->is_ptr = true;
out->_obj = obj;
return PyObject__slots(obj);
}
void py_newsliceint(py_OutRef out, py_i64 start, py_i64 stop, py_i64 step) {
py_Ref slots = py_newslice(out);
py_newint(&slots[0], start);
py_newint(&slots[1], stop);
py_newint(&slots[2], step);
}
static bool slice__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1 + 3);
py_Ref slice = py_retval();
py_newslice(slice);
py_setslot(slice, 0, py_arg(1));
py_setslot(slice, 1, py_arg(2));
py_setslot(slice, 2, py_arg(3));
return true;
}
static bool slice__repr__(int argc, py_Ref argv) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_cstr(&buf, "slice(");
for(int i = 0; i < 3; i++) {
py_TValue* val = py_getslot(argv, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
if(i != 2) c11_sbuf__write_cstr(&buf, ", ");
}
c11_sbuf__write_char(&buf, ')');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool slice_start(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 0);
py_assign(py_retval(), val);
return true;
}
static bool slice_stop(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 1);
py_assign(py_retval(), val);
return true;
}
static bool slice_step(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 2);
py_assign(py_retval(), val);
return true;
}
static bool slice__eq__(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_Ref other = py_arg(1);
if(!py_istype(other, tp_slice)) {
py_newnotimplemented(py_retval());
return true;
}
for(int i = 0; i < 3; i++) {
py_Ref lhs = py_getslot(self, i);
py_Ref rhs = py_getslot(other, i);
int res = py_equal(lhs, rhs);
if(res == -1) return false;
if(res == 0) {
py_newbool(py_retval(), false);
return true;
}
}
py_newbool(py_retval(), true);
return true;
}
static bool slice__ne__(int argc, py_Ref argv) {
bool ok = slice__eq__(argc, argv);
if(!ok) return false;
py_Ref res = py_retval();
if(py_isbool(res)) py_newbool(py_retval(), !py_tobool(res));
return true;
}
py_Type pk_slice__register() {
py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, slice__new__);
py_bindmagic(type, __repr__, slice__repr__);
py_bindmagic(type, __eq__, slice__eq__);
py_bindmagic(type, __ne__, slice__ne__);
py_setdict(py_tpobject(type), __hash__, py_None());
py_bindproperty(type, "start", slice_start, NULL);
py_bindproperty(type, "stop", slice_stop, NULL);
py_bindproperty(type, "step", slice_step, NULL);
return type;
}
// src/public\PythonOps.c
bool py_binaryadd(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __add__, __radd__); }
bool py_binarysub(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __sub__, __rsub__); }
bool py_binarymul(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __mul__, __rmul__); }
bool py_binarytruediv(py_Ref lhs, py_Ref rhs) {
return py_binaryop(lhs, rhs, __truediv__, __rtruediv__);
}
bool py_binaryfloordiv(py_Ref lhs, py_Ref rhs) {
return py_binaryop(lhs, rhs, __floordiv__, __rfloordiv__);
}
bool py_binarymod(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __mod__, __rmod__); }
bool py_binarypow(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __pow__, __rpow__); }
bool py_binarylshift(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __lshift__, 0); }
bool py_binaryrshift(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __rshift__, 0); }
bool py_binaryand(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __and__, 0); }
bool py_binaryor(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __or__, 0); }
bool py_binaryxor(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __xor__, 0); }
bool py_binarymatmul(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __matmul__, 0); }
bool py_eq(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __eq__, __eq__); }
bool py_ne(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __ne__, __ne__); }
bool py_lt(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __lt__, __gt__); }
bool py_le(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __le__, __ge__); }
bool py_gt(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __gt__, __lt__); }
bool py_ge(py_Ref lhs, py_Ref rhs) { return py_binaryop(lhs, rhs, __ge__, __le__); }
bool py_isidentical(py_Ref lhs, py_Ref rhs) {
if(lhs->type != rhs->type) return false;
switch(lhs->type) {
case tp_int: return lhs->_i64 == rhs->_i64;
case tp_float: return lhs->_f64 == rhs->_f64;
case tp_bool: return lhs->_bool == rhs->_bool;
case tp_str: {
if(lhs->is_ptr && rhs->is_ptr) {
return lhs->_obj == rhs->_obj;
} else {
return strcmp(lhs->_chars, rhs->_chars) == 0;
}
}
case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc;
case tp_NoneType: return true;
case tp_NotImplementedType: return true;
case tp_ellipsis: return true;
// fallback to pointer comparison
default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj;
}
}
int py_bool(py_Ref val) {
switch(val->type) {
case tp_bool: return val->_bool;
case tp_int: return val->_i64 != 0;
case tp_float: return val->_f64 != 0;
case tp_NoneType: return 0;
default: {
py_Ref tmp = py_tpfindmagic(val->type, __bool__);
if(tmp) {
if(!py_call(tmp, 1, val)) return -1;
if(!py_checkbool(py_retval())) return -1;
return py_tobool(py_retval());
} else {
tmp = py_tpfindmagic(val->type, __len__);
if(tmp) {
if(!py_call(tmp, 1, val)) return -1;
if(!py_checkint(py_retval())) return -1;
return py_toint(py_retval());
} else {
return 1; // True
}
}
}
}
}
int py_equal(py_Ref lhs, py_Ref rhs) {
if(py_isidentical(lhs, rhs)) return 1;
if(!py_eq(lhs, rhs)) return -1;
return py_bool(py_retval());
}
int py_less(py_Ref lhs, py_Ref rhs) {
if(!py_lt(lhs, rhs)) return -1;
return py_bool(py_retval());
}
bool py_callable(py_Ref val) {
switch(val->type) {
case tp_nativefunc: return true;
case tp_function: return true;
case tp_type: return true;
case tp_boundmethod: return true;
case tp_staticmethod: return true;
case tp_classmethod: return true;
default: return py_tpfindmagic(val->type, __call__);
}
}
bool py_hash(py_Ref val, int64_t* out) {
py_TypeInfo* ti = pk_typeinfo(val->type);
do {
py_Ref slot_hash = py_getdict(&ti->self, __hash__);
if(slot_hash && py_isnone(slot_hash)) break;
py_Ref slot_eq = py_getdict(&ti->self, __eq__);
if(slot_eq) {
if(!slot_hash) break;
if(!py_call(slot_hash, 1, val)) return false;
if(!py_checkint(py_retval())) return false;
*out = py_toint(py_retval());
return true;
}
ti = ti->base_ti;
} while(ti);
return TypeError("unhashable type: '%t'", val->type);
}
bool py_iter(py_Ref val) {
py_Ref tmp = py_tpfindmagic(val->type, __iter__);
if(!tmp) return TypeError("'%t' object is not iterable", val->type);
return py_call(tmp, 1, val);
}
int py_next(py_Ref val) {
VM* vm = pk_current_vm;
switch(val->type) {
case tp_generator:
if(generator__next__(1, val)) return 1;
break;
case tp_array2d_like_iterator:
if(array2d_like_iterator__next__(1, val)) return 1;
break;
case tp_list_iterator:
if(list_iterator__next__(1, val)) return 1;
break;
case tp_tuple_iterator:
if(tuple_iterator__next__(1, val)) return 1;
break;
case tp_dict_iterator:
if(dict_items__next__(1, val)) return 1;
break;
case tp_range_iterator:
if(range_iterator__next__(1, val)) return 1;
break;
case tp_str_iterator:
if(str_iterator__next__(1, val)) return 1;
break;
default: {
py_Ref tmp = py_tpfindmagic(val->type, __next__);
if(!tmp) {
TypeError("'%t' object is not an iterator", val->type);
return -1;
}
if(py_call(tmp, 1, val)) return 1;
break;
}
}
if(vm->unhandled_exc.type == tp_StopIteration) {
vm->last_retval = vm->unhandled_exc;
py_clearexc(NULL);
return 0;
}
return -1;
}
bool py_str(py_Ref val) {
if(val->type == tp_str) {
py_assign(py_retval(), val);
return true;
}
py_Ref tmp = py_tpfindmagic(val->type, __str__);
if(!tmp) return py_repr(val);
return py_call(tmp, 1, val);
}
bool py_repr(py_Ref val) { return pk_callmagic(__repr__, 1, val); }
bool py_len(py_Ref val) { return pk_callmagic(__len__, 1, val); }
bool py_getattr(py_Ref self, py_Name name) {
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
py_TypeInfo* ti = pk_typeinfo(self->type);
if(ti->getattribute) return ti->getattribute(self, name);
py_Ref cls_var = pk_tpfindname(ti, name);
if(cls_var) {
// handle descriptor
if(py_istype(cls_var, tp_property)) {
py_Ref getter = py_getslot(cls_var, 0);
return py_call(getter, 1, self);
}
}
// handle instance __dict__
if(self->is_ptr && self->_obj->slots == -1) {
if(!py_istype(self, tp_type)) {
py_Ref res = py_getdict(self, name);
if(res) {
py_assign(py_retval(), res);
return true;
}
} else {
// self is a type object
py_TypeInfo* inner_type = py_touserdata(self);
py_Ref res = pk_tpfindname(inner_type, name);
if(res) {
if(py_istype(res, tp_staticmethod)) {
res = py_getslot(res, 0);
} else if(py_istype(res, tp_classmethod)) {
res = py_getslot(res, 0);
py_newboundmethod(py_retval(), self, res);
return true;
}
py_assign(py_retval(), res);
return true;
}
}
}
if(cls_var) {
// bound method is non-data descriptor
switch(cls_var->type) {
case tp_function: {
if(name == __new__) goto __STATIC_NEW;
py_newboundmethod(py_retval(), self, cls_var);
return true;
}
case tp_nativefunc: {
if(name == __new__) goto __STATIC_NEW;
py_newboundmethod(py_retval(), self, cls_var);
return true;
}
case tp_staticmethod: {
py_assign(py_retval(), py_getslot(cls_var, 0));
return true;
}
case tp_classmethod: {
py_newboundmethod(py_retval(), &ti->self, py_getslot(cls_var, 0));
return true;
}
default: {
__STATIC_NEW:
py_assign(py_retval(), cls_var);
return true;
}
}
}
py_Ref fallback = pk_tpfindmagic(ti, __getattr__);
if(fallback) {
py_push(fallback);
py_push(self);
py_assign(py_pushtmp(), py_name2ref(name));
return py_vectorcall(1, 0);
}
if(self->type == tp_module) {
py_ModuleInfo* mi = py_touserdata(self);
c11_sbuf buf;
c11_sbuf__ctor(&buf);
pk_sprintf(&buf, "%v.%n", c11_string__sv(mi->path), name);
c11_string* new_path = c11_sbuf__submit(&buf);
int res = py_import(new_path->data);
c11_string__delete(new_path);
if(res == -1) {
return false;
} else if(res == 1) {
return true;
}
}
return AttributeError(self, name);
}
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
py_TypeInfo* ti = pk_typeinfo(self->type);
if(ti->setattribute) return ti->setattribute(self, name, val);
py_Ref cls_var = pk_tpfindname(ti, name);
if(cls_var) {
// handle descriptor
if(py_istype(cls_var, tp_property)) {
py_Ref setter = py_getslot(cls_var, 1);
if(!py_isnone(setter)) {
py_push(setter);
py_push(self);
py_push(val);
return py_vectorcall(1, 0);
} else {
return TypeError("readonly attribute: '%n'", name);
}
}
}
// handle instance __dict__
if(self->is_ptr && self->_obj->slots == -1) {
py_setdict(self, name, val);
return true;
}
return TypeError("cannot set attribute");
}
bool py_delattr(py_Ref self, py_Name name) {
py_TypeInfo* ti = pk_typeinfo(self->type);
if(ti->delattribute) return ti->delattribute(self, name);
if(self->is_ptr && self->_obj->slots == -1) {
if(py_deldict(self, name)) return true;
return AttributeError(self, name);
}
return TypeError("cannot delete attribute");
}
bool py_getitem(py_Ref self, py_Ref key) {
py_push(self);
py_push(key);
bool ok = pk_callmagic(__getitem__, 2, py_peek(-2));
py_shrink(2);
return ok;
}
bool py_setitem(py_Ref self, py_Ref key, py_Ref val) {
py_push(self);
py_push(key);
py_push(val);
bool ok = pk_callmagic(__setitem__, 3, py_peek(-3));
py_shrink(3);
return ok;
}
bool py_delitem(py_Ref self, py_Ref key) {
py_push(self);
py_push(key);
bool ok = pk_callmagic(__delitem__, 2, py_peek(-2));
py_shrink(2);
return ok;
}
// src/public\PyTuple.c
py_ObjectRef py_newtuple(py_OutRef out, int n) {
VM* vm = pk_current_vm;
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
out->type = tp_tuple;
out->is_ptr = true;
out->_obj = obj;
return PyObject__slots(obj);
}
py_Ref py_tuple_getitem(py_Ref self, int i) { return py_getslot(self, i); }
py_Ref py_tuple_data(py_Ref self) { return PyObject__slots(self->_obj); }
void py_tuple_setitem(py_Ref self, int i, py_Ref val) { py_setslot(self, i, val); }
int py_tuple_len(py_Ref self) { return self->_obj->slots; }
//////////////
static bool tuple__len__(int argc, py_Ref argv) {
py_newint(py_retval(), py_tuple_len(argv));
return true;
}
static bool tuple__repr__(int argc, py_Ref argv) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&buf, '(');
int length = py_tuple_len(argv);
for(int i = 0; i < length; i++) {
py_TValue* val = py_getslot(argv, i);
bool ok = py_repr(val);
if(!ok) {
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
if(i != length - 1) c11_sbuf__write_cstr(&buf, ", ");
}
if(length == 1) c11_sbuf__write_char(&buf, ',');
c11_sbuf__write_char(&buf, ')');
c11_sbuf__py_submit(&buf, py_retval());
return true;
}
static bool tuple__new__(int argc, py_Ref argv) {
if(argc == 1 + 0) {
py_newtuple(py_retval(), 0);
return true;
}
if(argc == 1 + 1) {
bool ok = py_tpcall(tp_list, 1, py_arg(1));
if(!ok) return false;
py_Ref tmp = py_pushtmp();
*tmp = *py_retval(); // backup the list
int length = py_list_len(tmp);
py_Ref p = py_newtuple(py_retval(), length);
for(int i = 0; i < py_tuple_len(py_retval()); i++) {
p[i] = *py_list_getitem(tmp, i);
}
py_pop();
return true;
}
return TypeError("tuple() takes at most 1 argument");
}
static bool tuple__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
int length = py_tuple_len(argv);
py_Ref _1 = py_arg(1);
if(_1->type == tp_int) {
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, length)) return false;
*py_retval() = *py_getslot(argv, index);
return true;
} else if(_1->type == tp_slice) {
int start, stop, step;
bool ok = pk__parse_int_slice(_1, length, &start, &stop, &step);
if(!ok) return false;
py_Ref tmp = py_pushtmp();
py_newlist(tmp);
PK_SLICE_LOOP(i, start, stop, step) py_list_append(tmp, py_getslot(argv, i));
// convert list to tuple
py_Ref p = py_newtuple(py_retval(), py_list_len(tmp));
for(int i = 0; i < py_tuple_len(py_retval()); i++) {
p[i] = *py_list_getitem(tmp, i);
}
py_pop();
return true;
} else {
return TypeError("tuple indices must be integers");
}
}
static bool tuple__eq__(int argc, py_Ref argv) {
return pk_wrapper__arrayequal(tp_tuple, argc, argv);
}
static bool tuple__ne__(int argc, py_Ref argv) {
if(!tuple__eq__(argc, argv)) return false;
if(py_isbool(py_retval())) {
bool res = py_tobool(py_retval());
py_newbool(py_retval(), !res);
}
return true;
}
static bool tuple__lt__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
if(!py_istype(py_arg(1), tp_tuple)) {
py_newnotimplemented(py_retval());
return true;
}
py_TValue *p0, *p1;
int lhs_length = py_tuple_len(py_arg(0));
int rhs_length = py_tuple_len(py_arg(1));
p0 = py_tuple_data(py_arg(0));
p1 = py_tuple_data(py_arg(1));
int length = lhs_length < rhs_length ? lhs_length : rhs_length;
for(int i = 0; i < length; i++) {
int res_lt = py_less(p0 + i, p1 + i);
if(res_lt == -1) return false;
if(res_lt) {
py_newbool(py_retval(), true);
return true;
} else {
int res_eq = py_equal(p0 + i, p1 + i);
if(res_eq == -1) return false;
if(!res_eq) {
py_newbool(py_retval(), false);
return true;
}
}
}
py_newbool(py_retval(), lhs_length < rhs_length);
return true;
}
static bool tuple__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
tuple_iterator* ud = py_newobject(py_retval(), tp_tuple_iterator, 1, sizeof(tuple_iterator));
ud->p = py_tuple_data(argv);
ud->length = py_tuple_len(argv);
ud->index = 0;
py_setslot(py_retval(), 0, argv); // keep a reference to the object
return true;
}
static bool tuple__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
return pk_arraycontains(py_arg(0), py_arg(1));
}
static bool tuple__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int length = py_tuple_len(argv);
py_TValue* data = py_tuple_data(argv);
uint64_t x = 1000003;
for(int i = 0; i < length; i++) {
py_i64 y;
if(!py_hash(&data[i], &y)) return false;
// recommended by Github Copilot
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
}
py_newint(py_retval(), x);
return true;
}
py_Type pk_tuple__register() {
py_Type type = pk_newtype("tuple", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __len__, tuple__len__);
py_bindmagic(type, __repr__, tuple__repr__);
py_bindmagic(type, __new__, tuple__new__);
py_bindmagic(type, __getitem__, tuple__getitem__);
py_bindmagic(type, __eq__, tuple__eq__);
py_bindmagic(type, __ne__, tuple__ne__);
py_bindmagic(type, __lt__, tuple__lt__);
py_bindmagic(type, __iter__, tuple__iter__);
py_bindmagic(type, __contains__, tuple__contains__);
py_bindmagic(type, __hash__, tuple__hash__);
return type;
}
// src/public\StackOps.c
PK_INLINE py_Ref py_peek(int i) {
assert(i <= 0);
return pk_current_vm->stack.sp + i;
}
PK_INLINE void py_push(py_Ref src) {
VM* vm = pk_current_vm;
*vm->stack.sp++ = *src;
}
PK_INLINE void py_pushnil() {
VM* vm = pk_current_vm;
py_newnil(vm->stack.sp++);
}
PK_INLINE void py_pushnone() {
VM* vm = pk_current_vm;
py_newnone(vm->stack.sp++);
}
PK_INLINE void py_pushname(py_Name name) {
VM* vm = pk_current_vm;
py_newint(vm->stack.sp++, (uintptr_t)name);
}
PK_INLINE void py_pop() {
VM* vm = pk_current_vm;
vm->stack.sp--;
}
PK_INLINE void py_shrink(int n) {
VM* vm = pk_current_vm;
vm->stack.sp -= n;
}
PK_INLINE py_Ref py_pushtmp() {
VM* vm = pk_current_vm;
return vm->stack.sp++;
}
PK_INLINE bool py_pushmethod(py_Name name) {
bool ok = pk_loadmethod(py_peek(-1), name);
if(ok) pk_current_vm->stack.sp++;
return ok;
}
bool py_pusheval(const char* expr, py_GlobalRef module) {
bool ok = py_exec(expr, "<string>", EVAL_MODE, module);
if(!ok) return false;
py_push(py_retval());
return true;
}
PK_INLINE bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
return VM__vectorcall(pk_current_vm, argc, kwargc, false) != RES_ERROR;
}
bool py_call(py_Ref f, int argc, py_Ref argv) {
if(f->type == tp_nativefunc) {
return py_callcfunc(f->_cfunc, argc, argv);
} else {
py_push(f);
py_pushnil();
for(int i = 0; i < argc; i++)
py_push(py_offset(argv, i));
bool ok = py_vectorcall(argc, 0);
return ok;
}
}
#ifndef NDEBUG
bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
if(py_checkexc()) {
const char* name = py_tpname(pk_current_vm->unhandled_exc.type);
c11__abort("unhandled exception `%s` was set!", name);
}
py_StackRef p0 = py_peek(0);
// NOTE: sometimes users are using `py_retval()` to pass `argv`
// It will be reset to `nil` and cause an exception
py_newnil(py_retval());
bool ok = f(argc, argv);
if(!ok) {
if(!py_checkexc()) { c11__abort("py_CFunction returns `false` but no exception is set!"); }
return false;
}
if(py_peek(0) != p0) {
c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?");
}
if(py_isnil(py_retval())) {
c11__abort(
"py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
}
if(py_checkexc()) {
const char* name = py_tpname(pk_current_vm->unhandled_exc.type);
c11__abort("py_CFunction returns `true`, but `%s` was set!", name);
}
return true;
}
#endif
bool py_tpcall(py_Type type, int argc, py_Ref argv) {
return py_call(py_tpobject(type), argc, argv);
}
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
py_push(lhs);
py_push(rhs);
bool ok = pk_stack_binaryop(pk_current_vm, op, rop);
py_shrink(2);
return ok;
}
bool pk_loadmethod(py_StackRef self, py_Name name) {
// NOTE: `out` and `out_self` may overlap with `self`
py_Type type;
if(name == __new__) {
// __new__ acts like a @staticmethod
if(self->type == tp_type) {
// T.__new__(...)
type = py_totype(self);
} else if(self->type == tp_super) {
// super(T, obj).__new__(...)
type = *(py_Type*)py_touserdata(self);
} else {
// invalid usage of `__new__`
return false;
}
py_Ref cls_var = py_tpfindmagic(type, name);
if(cls_var) {
self[0] = *cls_var;
self[1] = *py_NIL();
return true;
}
return false;
}
py_TValue self_bak; // to avoid overlapping
// handle super() proxy
if(py_istype(self, tp_super)) {
type = *(py_Type*)py_touserdata(self);
// BUG: here we modify `self` which refers to the stack directly
// If `pk_loadmethod` fails, `self` will be corrupted
self_bak = *py_getslot(self, 0);
} else {
type = self->type;
self_bak = *self;
}
py_TypeInfo* ti = pk_typeinfo(type);
if(ti->getunboundmethod) {
bool ok = ti->getunboundmethod(self, name);
if(ok) {
assert(py_retval()->type == tp_nativefunc || py_retval()->type == tp_function);
self[0] = *py_retval();
self[1] = self_bak;
return true;
} else {
return false;
}
}
py_Ref cls_var = pk_tpfindname(ti, name);
if(cls_var != NULL) {
switch(cls_var->type) {
case tp_function:
case tp_nativefunc: {
self[0] = *cls_var;
self[1] = self_bak;
break;
}
case tp_staticmethod:
self[0] = *py_getslot(cls_var, 0);
self[1] = *py_NIL();
break;
case tp_classmethod:
self[0] = *py_getslot(cls_var, 0);
self[1] = ti->self;
break;
default: return false;
}
return true;
}
return false;
}
bool pk_callmagic(py_Name name, int argc, py_Ref argv) {
assert(argc >= 1);
// assert(py_ismagicname(name));
py_Ref tmp = py_tpfindmagic(argv->type, name);
if(!tmp) return AttributeError(argv, name);
return py_call(tmp, argc, argv);
}
// src/public\TypeSystem.c
py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) {
if(strlen(name) == 0) c11__abort("type name cannot be empty");
py_Type type = pk_newtype(name, base, module, dtor, false, false);
if(module) py_setdict(module, py_name(name), py_tpobject(type));
return type;
}
PK_INLINE bool py_istype(py_Ref self, py_Type type) { return self->type == type; }
PK_INLINE py_Type py_typeof(py_Ref self) { return self->type; }
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
bool py_issubclass(py_Type derived, py_Type base) {
assert(derived != 0 && base != 0);
py_TypeInfo* derived_ti = pk_typeinfo(derived);
py_TypeInfo* base_ti = pk_typeinfo(base);
do {
if(derived_ti == base_ti) return true;
derived_ti = derived_ti->base_ti;
} while(derived_ti);
return false;
}
py_Type py_gettype(const char* module, py_Name name) {
py_Ref mod;
if(module != NULL) {
mod = py_getmodule(module);
if(!mod) return tp_nil;
} else {
mod = pk_current_vm->builtins;
}
py_Ref object = py_getdict(mod, name);
if(object && py_istype(object, tp_type)) return py_totype(object);
return tp_nil;
}
bool py_checktype(py_Ref self, py_Type type) {
if(self->type == type) return true;
return TypeError("expected '%t', got '%t'", type, self->type);
}
bool py_checkinstance(py_Ref self, py_Type type) {
if(py_isinstance(self, type)) return true;
return TypeError("expected '%t' or its subclass, got '%t'", type, self->type);
}
PK_DEPRECATED py_Ref py_tpgetmagic(py_Type type, py_Name name) {
// assert(py_ismagicname(name));
py_TypeInfo* ti = pk_typeinfo(type);
py_Ref retval = py_getdict(&ti->self, name);
return retval != NULL ? retval : py_NIL();
}
PK_INLINE py_Ref py_tpfindmagic(py_Type t, py_Name name) {
// assert(py_ismagicname(name));
return py_tpfindname(t, name);
}
PK_INLINE py_ItemRef py_tpfindname(py_Type type, py_Name name) {
py_TypeInfo* ti = pk_typeinfo(type);
return pk_tpfindname(ti, name);
}
PK_INLINE py_Type py_tpbase(py_Type t) {
assert(t);
py_TypeInfo* ti = pk_typeinfo(t);
return ti->base;
}
py_Ref py_tpobject(py_Type type) {
assert(type);
return &pk_typeinfo(type)->self;
}
const char* py_tpname(py_Type type) {
if(!type) return "nil";
py_Name name = pk_typeinfo(type)->name;
return py_name2str(name);
}
void py_tpsetfinal(py_Type type) {
assert(type);
py_TypeInfo* ti = pk_typeinfo(type);
ti->is_final = true;
}
void py_tphookattributes(py_Type type,
bool (*getattribute)(py_Ref self, py_Name name),
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
bool (*delattribute)(py_Ref self, py_Name name),
bool (*getunboundmethod)(py_Ref self, py_Name name)) {
assert(type);
py_TypeInfo* ti = pk_typeinfo(type);
ti->getattribute = getattribute;
ti->setattribute = setattribute;
ti->delattribute = delattribute;
ti->getunboundmethod = getunboundmethod;
}
// src/public\ValueCast.c
py_i64 py_toint(py_Ref self) {
assert(self->type == tp_int);
return self->_i64;
}
void* py_totrivial(py_Ref self) { return &self->_chars; }
double py_tofloat(py_Ref self) {
assert(self->type == tp_float);
return self->_f64;
}
bool py_castfloat(py_Ref self, double* out) {
switch(self->type) {
case tp_int: *out = (double)self->_i64; return true;
case tp_float: *out = self->_f64; return true;
default: return TypeError("expected 'int' or 'float', got '%t'", self->type);
}
}
bool py_castfloat32(py_Ref self, float* out) {
switch(self->type) {
case tp_int: *out = (float)self->_i64; return true;
case tp_float: *out = (float)self->_f64; return true;
default: return TypeError("expected 'int' or 'float', got '%t'", self->type);
}
}
bool py_castint(py_Ref self, int64_t* out) {
if(self->type == tp_int) {
*out = self->_i64;
return true;
}
return TypeError("expected 'int', got '%t'", self->type);
}
bool py_tobool(py_Ref self) {
assert(self->type == tp_bool);
return self->_bool;
}
py_Type py_totype(py_Ref self) {
assert(self->type == tp_type);
py_TypeInfo* ud = py_touserdata(self);
return ud->index;
}
void* py_touserdata(py_Ref self) {
assert(self && self->is_ptr);
return PyObject__userdata(self->_obj);
}
const char* py_tostr(py_Ref self) { return pk_tostr(self)->data; }
const char* py_tostrn(py_Ref self, int* size) {
c11_string* ud = pk_tostr(self);
*size = ud->size;
return ud->data;
}
c11_sv py_tosv(py_Ref self) {
c11_string* ud = pk_tostr(self);
return c11_string__sv(ud);
}
unsigned char* py_tobytes(py_Ref self, int* size) {
assert(self->type == tp_bytes);
c11_bytes* ud = PyObject__userdata(self->_obj);
*size = ud->size;
return ud->data;
}
void py_bytes_resize(py_Ref self, int size) {
assert(self->type == tp_bytes);
c11_bytes* ud = PyObject__userdata(self->_obj);
if(size > ud->size) c11__abort("bytes can only be resized down: %d > %d", ud->size, size);
ud->size = size;
}
// src/public\ValueCreation.c
void py_newint(py_OutRef out, py_i64 val) {
out->type = tp_int;
out->is_ptr = false;
out->_i64 = val;
}
void py_newtrivial(py_OutRef out, py_Type type, void* data, int size) {
out->type = type;
out->is_ptr = false;
assert(size <= 16);
memcpy(&out->_chars, data, size);
}
void py_newfloat(py_OutRef out, py_f64 val) {
out->type = tp_float;
out->is_ptr = false;
out->_f64 = val;
}
void py_newbool(py_OutRef out, bool val) {
out->type = tp_bool;
out->is_ptr = false;
out->_bool = val;
}
void py_newstr(py_OutRef out, const char* data) { py_newstrv(out, (c11_sv){data, strlen(data)}); }
char* py_newstrn(py_OutRef out, int size) {
if(size < 16) {
out->type = tp_str;
out->is_ptr = false;
c11_string* ud = (c11_string*)(&out->extra);
c11_string__ctor3(ud, size);
return ud->data;
}
ManagedHeap* heap = &pk_current_vm->heap;
int total_size = sizeof(c11_string) + size + 1;
PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size);
c11_string* ud = PyObject__userdata(obj);
c11_string__ctor3(ud, size);
out->type = tp_str;
out->is_ptr = true;
out->_obj = obj;
return ud->data;
}
void py_newstrv(py_OutRef out, c11_sv sv) {
char* data = py_newstrn(out, sv.size);
memcpy(data, sv.data, sv.size);
}
void py_newfstr(py_OutRef out, const char* fmt, ...) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
va_list args;
va_start(args, fmt);
pk_vsprintf(&buf, fmt, args);
va_end(args);
c11_sbuf__py_submit(&buf, out);
}
unsigned char* py_newbytes(py_OutRef out, int size) {
ManagedHeap* heap = &pk_current_vm->heap;
// 4 bytes size + data
PyObject* obj = ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
c11_bytes* ud = PyObject__userdata(obj);
ud->size = size;
out->type = tp_bytes;
out->is_ptr = true;
out->_obj = obj;
return ud->data;
}
void py_newnone(py_OutRef out) {
out->type = tp_NoneType;
out->is_ptr = false;
}
void py_newnotimplemented(py_OutRef out) {
out->type = tp_NotImplementedType;
out->is_ptr = false;
}
void py_newellipsis(py_OutRef out) {
out->type = tp_ellipsis;
out->is_ptr = false;
}
void py_newnil(py_OutRef out) {
out->type = tp_nil;
out->is_ptr = false;
}
void py_newnativefunc(py_OutRef out, py_CFunction f) {
out->type = tp_nativefunc;
out->is_ptr = false;
out->_cfunc = f;
}
py_Name py_newfunction(py_OutRef out,
const char* sig,
py_CFunction f,
const char* docstring,
int slots) {
char buffer[256];
snprintf(buffer, sizeof(buffer), "def %s: pass", sig);
// fn(a, b, *c, d=1) -> None
CodeObject code;
SourceData_ source = SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
Error* err = pk_compile(source, &code);
if(err || code.func_decls.length != 1) {
c11__abort("py_newfunction(): invalid signature '%s'", sig);
}
FuncDecl_ decl = c11__getitem(FuncDecl_, &code.func_decls, 0);
if(docstring) decl->docstring = c11_strdup(docstring);
// construct the function
Function* ud = py_newobject(out, tp_function, slots, sizeof(Function));
Function__ctor(ud, decl, NULL, NULL);
ud->cfunc = f;
CodeObject__dtor(&code);
PK_DECREF(source);
assert(decl->rc.count == 1);
py_Name decl_name = py_name(ud->decl->code.name->data);
if(decl_name == __new__ || decl_name == __init__) {
if(ud->decl->args.length == 0) {
c11__abort("%s() should have at least one positional argument", py_name2str(decl_name));
}
}
return decl_name;
}
void py_newboundmethod(py_OutRef out, py_Ref self, py_Ref func) {
py_newobject(out, tp_boundmethod, 2, 0);
py_setslot(out, 0, self);
py_setslot(out, 1, func);
}
void* py_newobject(py_OutRef out, py_Type type, int slots, int udsize) {
ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize);
out->type = type;
out->is_ptr = true;
out->_obj = obj;
return PyObject__userdata(obj);
}