builtins.cpp 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134
  1. /* Definitions for builtin functions.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #include <cstdio>
  14. #include <new>
  15. #include "khipu.hpp"
  16. #include "utils/lazy.hpp"
  17. KP_DECLS_BEGIN
  18. static exception
  19. invalid_arg (interpreter *interp, const char *name)
  20. {
  21. char buf[128];
  22. sprintf (buf, "invalid argument(s) passed to '%s'", name);
  23. return (interp->raise ("arg-error", buf));
  24. }
  25. static result<int64_t>
  26. write_generic (interpreter *interp, stream *strm,
  27. object obj, io_info& info)
  28. {
  29. char buf[64];
  30. int64_t ret = KP_TRY (strm->write (interp, "#<", 2));
  31. ret += KP_TRY (write_S (interp, strm, type_name (type (obj)), info));
  32. ret += KP_TRY (strm->write (interp, " object at ", 11));
  33. ret += KP_TRY (strm->write (interp, buf, sprintf (buf, "%p", unmask (obj))));
  34. ret += KP_TRY (strm->putb (interp, '>'));
  35. return (ret);
  36. }
  37. #define INTERN(name) \
  38. intern (interp, name, sizeof (name) - 1, as_package (root_package))
  39. #define INTERN_N(name) \
  40. intern (interp, name, as_package (root_package))
  41. static inline object
  42. safe_symval (result<object> obj)
  43. {
  44. return (symbol_p (*obj) ? symval (*obj) : UNBOUND);
  45. }
  46. static result<object>
  47. call_binary (interpreter *interp, object x, object y,
  48. result<object> (*fn) (interpreter *, object , object),
  49. const char *method)
  50. {
  51. object ret = KP_TRY (fn (interp, x, y));
  52. if (ret != UNBOUND)
  53. return (interp->retval);
  54. KP_PUSH_ALL (interp, safe_symval (INTERN_N (method)), x, y);
  55. bool rv = KP_TRY (method_call (interp, 2));
  56. if (rv)
  57. return (interp->retval);
  58. valref sub_x (interp, builtin_member (x));
  59. valref sub_y (interp, builtin_member (y));
  60. if (*sub_x != UNBOUND && *sub_y != UNBOUND)
  61. {
  62. ret = KP_TRY (fn (interp, *sub_x, *sub_y));
  63. if (ret != UNBOUND)
  64. return (interp->retval);
  65. }
  66. return (interp->raise ("type-error",
  67. KP_SPRINTF (interp, "invalid types: got %Q and %Q",
  68. type (x), type (y))));
  69. }
  70. static result<int64_t>
  71. write_any (interpreter *interp, stream *strm,
  72. object obj, io_info& info)
  73. {
  74. KP_PUSH_ALL (interp, safe_symval (INTERN ("g-write")), obj, strm->as_obj ());
  75. bool rv = KP_TRY (method_call (interp, 2));
  76. if (rv)
  77. return (0);
  78. object tname = type_name (obj);
  79. if (tname == NIL)
  80. return (write_generic (interp, strm, obj, info));
  81. int64_t ret = KP_TRY (strm->write (interp, "#<type ", 7));
  82. ret += KP_TRY (xwrite (interp, strm, tname, info));
  83. ret += KP_TRY (strm->putb (interp, '>'));
  84. return (ret);
  85. }
  86. result<int64_t> xwrite (interpreter *interp, stream *strm,
  87. object obj, io_info& info)
  88. {
  89. int64_t ret;
  90. int itp = itype (obj);
  91. switch (itp)
  92. {
  93. #define DISPATCH(type, suffix) \
  94. case typecode::type: \
  95. ret = KP_TRY (write_##suffix (interp, strm, obj, info)); \
  96. break
  97. DISPATCH (INT, i);
  98. DISPATCH (CHAR, c);
  99. DISPATCH (CONS, L);
  100. DISPATCH (BIGINT, I);
  101. DISPATCH (FLOAT, f);
  102. DISPATCH (BIGFLOAT, F);
  103. DISPATCH (BVECTOR, b);
  104. DISPATCH (STR, s);
  105. DISPATCH (ARRAY, a);
  106. DISPATCH (TABLE, u);
  107. DISPATCH (TUPLE, o);
  108. DISPATCH (SYMBOL, S);
  109. DISPATCH (FCT, x);
  110. DISPATCH (PKG, P);
  111. default:
  112. if (obj == UNBOUND)
  113. { ret = KP_TRY (strm->write (interp, "#<unbound>", 10)); }
  114. else if (itp == typecode::CORO || itp == typecode::STREAM ||
  115. (info.flags & io_info::FLG_SAFE))
  116. { ret = KP_TRY (write_generic (interp, strm, obj, info)); }
  117. else
  118. { ret = KP_TRY (write_any (interp, strm, obj, info)); }
  119. #undef DISPATCH
  120. }
  121. return (strm->err_p () ? -1 : ret);
  122. }
  123. static inline bool
  124. ref_obj_p (object obj, int tp)
  125. {
  126. switch (tp)
  127. {
  128. case typecode::INT:
  129. case typecode::CHAR:
  130. return (false);
  131. case typecode::PKG:
  132. return (obj != root_package && obj != kword_package);
  133. case typecode::FCT:
  134. return (!as_varobj(obj)->flagged_p (function::artificial_flag));
  135. default:
  136. return (true);
  137. }
  138. }
  139. result<int64_t> xpack (interpreter *interp, stream *strm,
  140. object obj, pack_info& info)
  141. {
  142. int64_t ret = 0;
  143. int tp = itype (obj);
  144. if (nil_p (obj))
  145. return (strm->putb (interp, PACK_NIL));
  146. else if (array_p (obj) && len_a (obj) == 0)
  147. return (strm->putb (interp, PACK_EMPTY_ARRAY));
  148. else if ((str_p (obj) || bvector_p (obj)) && as_bvector(obj)->nbytes == 0)
  149. return (strm->putb (interp, str_p (obj) ?
  150. PACK_EMPTY_STR : PACK_EMPTY_BVECTOR));
  151. else if (tp == typecode::CHAR && as_char (obj) <= 0xff)
  152. {
  153. unsigned char data[] = { PACK_CHAR8, (unsigned char)as_char (obj) };
  154. return (strm->write (interp, data, sizeof (data)));
  155. }
  156. else if (tp == typecode::INT && as_int (obj) <= 0x7f && as_int (obj) >= -128)
  157. {
  158. unsigned char data[] = { PACK_INT8, (unsigned char)as_int (obj) };
  159. return (strm->write (interp, data, sizeof (data)));
  160. }
  161. else if (tp == typecode::INSTANCE && builtin_typespec_p (obj))
  162. {
  163. unsigned char data[] = { PACK_TYPESPEC,
  164. (unsigned char)as_instance(obj)->type_code () };
  165. return (strm->write (interp, data, sizeof (data)));
  166. }
  167. {
  168. object off = info.get (interp, obj);
  169. if (off != UNBOUND)
  170. {
  171. int ioff = as_int (off);
  172. info.touch (interp, ioff);
  173. ret += KP_TRY (strm->putb (interp, PACK_REF_INT32));
  174. ret += KP_TRY (strm->write (interp, &ioff));
  175. return (ret);
  176. }
  177. }
  178. if (ref_obj_p (obj, tp))
  179. {
  180. object pos = KP_TRY (strm->tell (interp));
  181. KP_VTRY (info.add_mapping (interp, obj, pos));
  182. }
  183. ret += KP_TRY (strm->putb (interp, tp));
  184. switch (tp)
  185. {
  186. #define DISPATCH(type, suffix) \
  187. case typecode::type: \
  188. ret += KP_TRY (pack_##suffix (interp, strm, obj, info)); \
  189. break
  190. DISPATCH (INT, i);
  191. DISPATCH (CHAR, c);
  192. DISPATCH (CONS, L);
  193. DISPATCH (BIGINT, I);
  194. DISPATCH (FLOAT, f);
  195. DISPATCH (BIGFLOAT, F);
  196. DISPATCH (BVECTOR, b);
  197. DISPATCH (STR, s);
  198. DISPATCH (ARRAY, a);
  199. DISPATCH (TABLE, u);
  200. DISPATCH (TUPLE, o);
  201. DISPATCH (SYMBOL, S);
  202. DISPATCH (FCT, x);
  203. DISPATCH (CORO, G);
  204. DISPATCH (PKG, P);
  205. DISPATCH (INSTANCE, w);
  206. default:
  207. // XXX: Other objects.
  208. return (invalid_arg (interp, "pack"));
  209. #undef DISPATCH
  210. }
  211. return (strm->err_p () ? -1 : ret);
  212. }
  213. result<object> xunpack (interpreter *interp, stream *strm, pack_info& info)
  214. {
  215. object ret = KP_TRY (strm->tell (interp));
  216. *info.offset = KP_TRY (copy (interp, ret));
  217. int tp = KP_TRY (strm->getb (interp));
  218. if (tp < 0)
  219. return (info.error ("failed to read typecode"));
  220. bool save = (tp & 0x80) != 0;
  221. tp &= ~0x80;
  222. switch (tp)
  223. {
  224. case PACK_NIL:
  225. kp_return (NIL);
  226. case PACK_EMPTY_ARRAY:
  227. kp_return (deref (alloc_array (interp, 0)));
  228. case PACK_EMPTY_BVECTOR:
  229. kp_return (deref (alloc_bvector (interp, 0)));
  230. case PACK_EMPTY_STR:
  231. kp_return (deref (alloc_str (interp, 0)));
  232. case PACK_INT8:
  233. case PACK_CHAR8:
  234. {
  235. int b = KP_TRY (strm->getb (interp));
  236. if (b < 0)
  237. return (info.error ("failed to read byte"));
  238. kp_return (tp == PACK_INT8 ? fixint ((int8_t)b) :
  239. charobj ((uint8_t)b));
  240. }
  241. case PACK_REF_INT32:
  242. {
  243. int off;
  244. bool rv = KP_TRY (strm->sread (interp, &off));
  245. if (!rv)
  246. return (info.error ("failed to read integer"));
  247. interp->retval = info.get (interp, intobj (interp, off));
  248. if (interp->retval == UNBOUND)
  249. return (info.error ("invalid back reference to object"));
  250. return (interp->retval);
  251. }
  252. case PACK_REF_OBJ:
  253. {
  254. object rv = KP_TRY (xunpack (interp, strm, info));
  255. if ((interp->retval = info.get (interp, rv)) == UNBOUND)
  256. return (info.error ("invalid back reference to object"));
  257. return (interp->retval);
  258. }
  259. case PACK_TYPESPEC:
  260. tp = KP_TRY (strm->getb (interp));
  261. if (tp < 0)
  262. return (info.error ("failed to read typespec code"));
  263. else if ((interp->retval = builtin_type (tp)) == UNBOUND)
  264. return (info.error ("invalid typespec"));
  265. return (interp->retval);
  266. #define DISPATCH(type, suffix) \
  267. case typecode::type: \
  268. ret = KP_TRY (unpack_##suffix (interp, strm, info, save)); \
  269. break
  270. DISPATCH (INT, i);
  271. DISPATCH (CHAR, c);
  272. DISPATCH (CONS, L);
  273. DISPATCH (BIGINT, I);
  274. DISPATCH (FLOAT, f);
  275. DISPATCH (BIGFLOAT, F);
  276. DISPATCH (BVECTOR, b);
  277. DISPATCH (STR, s);
  278. DISPATCH (ARRAY, a);
  279. DISPATCH (TABLE, u);
  280. DISPATCH (TUPLE, o);
  281. DISPATCH (SYMBOL, S);
  282. DISPATCH (FCT, x);
  283. DISPATCH (CORO, G);
  284. DISPATCH (PKG, P);
  285. DISPATCH (INSTANCE, w);
  286. default:
  287. // XXX: Other objects.
  288. return (invalid_arg (interp, "unpack"));
  289. #undef DISPATCH
  290. }
  291. kp_return (ret);
  292. }
  293. result<object> copy (interpreter *interp, object obj, bool deep)
  294. {
  295. if (immediate_p (obj) || (varobj_p (obj) &&
  296. (as_varobj(obj)->flagged_p (FLAGS_CONST))))
  297. kp_return (obj);
  298. switch (itype (obj))
  299. {
  300. #define DISPATCH(type, suffix) \
  301. case typecode::type: \
  302. KP_VTRY (copy_##suffix (interp, obj, deep)); \
  303. return (interp->retval)
  304. DISPATCH (CONS, L);
  305. DISPATCH (BVECTOR, b);
  306. DISPATCH (ARRAY, a);
  307. DISPATCH (TABLE, u);
  308. DISPATCH (TUPLE, o);
  309. DISPATCH (SYMBOL, S);
  310. default:
  311. return (invalid_arg (interp, "copy"));
  312. #undef DISPATCH
  313. }
  314. }
  315. uint32_t hash_addr (object obj)
  316. {
  317. #ifndef KP_ARCH_WIDE
  318. return ((uint32_t)obj >> 3);
  319. #else
  320. return (mix_hash (obj >> 32, obj & 0xffffffff));
  321. #endif
  322. }
  323. static result<uint32_t>
  324. hash_helper (interpreter *interp, object obj, bool& got)
  325. {
  326. uint32_t ret;
  327. got = true;
  328. switch (itype (obj))
  329. {
  330. #define DISPATCH(type, suffix) \
  331. case typecode::type: \
  332. ret = KP_TRY (hash_##suffix (interp, obj)); \
  333. return (ret)
  334. #define hash_w(ip, x) (bool)(got = false)
  335. DISPATCH (CONS, L);
  336. DISPATCH (BIGINT, I);
  337. DISPATCH (FLOAT, f);
  338. DISPATCH (BIGFLOAT, F);
  339. DISPATCH (BVECTOR, b);
  340. DISPATCH (STR, s);
  341. DISPATCH (ARRAY, a);
  342. DISPATCH (TABLE, u);
  343. DISPATCH (TUPLE, o);
  344. DISPATCH (SYMBOL, S);
  345. DISPATCH (PKG, P);
  346. DISPATCH (INSTANCE, w);
  347. #undef DISPATCH
  348. #undef hash_w
  349. default:
  350. return (hash_addr (obj));
  351. }
  352. }
  353. result<uint32_t> xhash (interpreter *interp, object obj)
  354. {
  355. bool got;
  356. uint32_t ret = KP_TRY (hash_helper (interp, obj, got));
  357. if (got)
  358. return (ret);
  359. KP_PUSH_ALL (interp, safe_symval (INTERN ("g-hash")), obj);
  360. got = KP_TRY (method_call (interp, 1));
  361. if (got)
  362. {
  363. int iv;
  364. if (as<int> (interp->retval, iv))
  365. return (iv);
  366. else if (bigint *lp = as<bigint> (interp->retval))
  367. return (hash_I (interp, lp->as_obj ()));
  368. return (interp->raise ("type-error",
  369. "hash function must return an integer"));
  370. }
  371. valref sub_obj (interp, builtin_member (obj));
  372. if (*sub_obj != UNBOUND)
  373. return (hash_helper (interp, *sub_obj, got));
  374. return (ret);
  375. }
  376. result<object> length (interpreter *interp, object obj)
  377. {
  378. switch (itype (obj))
  379. {
  380. case typecode::ARRAY:
  381. return (fixint (len_a (obj)));
  382. case typecode::TUPLE:
  383. return (fixint (len_o (obj)));
  384. case typecode::BVECTOR:
  385. return (fixint (len_b (obj)));
  386. case typecode::STR:
  387. return (fixint (len_s (obj)));
  388. case typecode::TABLE:
  389. return (fixint (len_u (obj)));
  390. case typecode::CONS:
  391. {
  392. auto ret = KP_TRY (len_L (interp, obj));
  393. return (fixint (ret));
  394. }
  395. default:
  396. {
  397. KP_PUSH_ALL (interp, safe_symval (INTERN ("g-len")), obj);
  398. bool rv = KP_TRY (method_call (interp, 1));
  399. if (rv)
  400. return (interp->raise ("dispatch-error",
  401. "no applicable method found for g-len"));
  402. int out;
  403. if (as<int> (interp->retval, out) || as<bigint> (interp->retval))
  404. return (interp->retval);
  405. return (interp->raise ("type-error", "len must return an integer"));
  406. }
  407. }
  408. }
  409. // Binary operations.
  410. #define MIX(t1, t2) ((t1) + ((t2) * typecode::LAST))
  411. static result<object>
  412. add_helper (interpreter *interp, object x, object y)
  413. {
  414. object ret;
  415. switch (MIX (itype (x), itype (y)))
  416. {
  417. #define DISPATCH_1(type, suffix) \
  418. case MIX (typecode::type, typecode::type): \
  419. ret = KP_TRY (add_##suffix##suffix (interp, x, y)); \
  420. return (ret)
  421. #define DISPATCH_2(t1, t2, s1, s2) \
  422. case MIX (typecode::t1, typecode::t2): \
  423. ret = KP_TRY (add_##s1##s2 (interp, x, y)); \
  424. return (ret); \
  425. case MIX (typecode::t2, typecode::t1): \
  426. ret = KP_TRY (add_##s1##s2 (interp, y, x)); \
  427. return (ret)
  428. DISPATCH_1 (INT, i);
  429. DISPATCH_2 (INT, BIGINT, i, I);
  430. DISPATCH_2 (INT, FLOAT, i, f);
  431. DISPATCH_2 (INT, BIGFLOAT, i, F);
  432. DISPATCH_1 (BIGINT, I);
  433. DISPATCH_2 (BIGINT, FLOAT, I, f);
  434. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  435. DISPATCH_1 (FLOAT, f);
  436. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  437. DISPATCH_1 (BIGFLOAT, F);
  438. DISPATCH_1 (CHAR, c);
  439. DISPATCH_1 (STR, s);
  440. // Need to handle this case manually, since addition is not commutative.
  441. case MIX (typecode::STR, typecode::CHAR):
  442. return (add_sc (interp, x, y));
  443. case MIX (typecode::CHAR, typecode::STR):
  444. return (add_cs (interp, x, y));
  445. DISPATCH_1 (BVECTOR, b);
  446. DISPATCH_1 (ARRAY, a);
  447. DISPATCH_1 (CONS, L);
  448. default:
  449. return (UNBOUND);
  450. #undef DISPATCH_1
  451. #undef DISPATCH_2
  452. }
  453. }
  454. result<object> add (interpreter *interp, object x, object y)
  455. {
  456. return (call_binary (interp, x, y, add_helper, "g-add"));
  457. }
  458. #ifndef KP_ARCH_WIDE
  459. template <typename T>
  460. static inline void inplace_neg (T& val)
  461. {
  462. val = -val;
  463. }
  464. #endif
  465. static result<object>
  466. sub_helper (interpreter *interp, object x, object y)
  467. {
  468. object ret;
  469. switch (MIX (itype (x), itype (y)))
  470. {
  471. #define DISPATCH_1(type, suffix) \
  472. case MIX (typecode::type, typecode::type): \
  473. ret = KP_TRY (sub_##suffix##suffix (interp, x, y)); \
  474. return (ret)
  475. #define DISPATCH_2(t1, t2, s1, s2) \
  476. case MIX (typecode::t1, typecode::t2): \
  477. ret = KP_TRY (sub_##s1##s2 (interp, x, y)); \
  478. return (ret); \
  479. case MIX (typecode::t2, typecode::t1): \
  480. ret = KP_TRY (sub_##s1##s2 (interp, y, x)); \
  481. break
  482. DISPATCH_1 (INT, i);
  483. DISPATCH_2 (INT, BIGINT, i, I);
  484. DISPATCH_2 (INT, FLOAT, i, f);
  485. DISPATCH_2 (INT, BIGFLOAT, i, F);
  486. DISPATCH_1 (BIGINT, I);
  487. DISPATCH_2 (BIGINT, FLOAT, I, f);
  488. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  489. DISPATCH_1 (FLOAT, f);
  490. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  491. DISPATCH_1 (BIGFLOAT, F);
  492. default:
  493. return (UNBOUND);
  494. }
  495. #undef DISPATCH_1
  496. #undef DISPATCH_2
  497. /* Instead of doing (x - y), we performed (y - x), so we now have to
  498. * negate the result. We can do this in-place, since the return value
  499. * can only be seen by us. */
  500. if (fixint_p (ret))
  501. (void)neg_i (interp, ret);
  502. else if (varobj_p (ret))
  503. #ifdef KP_ARCH_WIDE
  504. ret ^= SIGN_BIT;
  505. #else
  506. switch (itype (ret))
  507. {
  508. case typecode::BIGINT:
  509. inplace_neg (as_bigint(ret)->len);
  510. break;
  511. case typecode::FLOAT:
  512. inplace_neg (as_fltobj(ret)->val);
  513. break;
  514. case typecode::BIGFLOAT:
  515. inplace_neg (as_bigfloat(ret)->len);
  516. break;
  517. }
  518. #endif
  519. kp_return (ret);
  520. }
  521. result<object> sub (interpreter *interp, object x, object y)
  522. {
  523. return (call_binary (interp, x, y, sub_helper, "g-sub"));
  524. }
  525. static result<object>
  526. mul_helper (interpreter *interp, object x, object y)
  527. {
  528. object ret;
  529. switch (MIX (itype (x), itype (y)))
  530. {
  531. #define DISPATCH_1(type, suffix) \
  532. case MIX (typecode::type, typecode::type): \
  533. ret = KP_TRY (mul_##suffix##suffix (interp, x, y)); \
  534. return (ret)
  535. #define DISPATCH_2(t1, t2, s1, s2) \
  536. case MIX (typecode::t1, typecode::t2): \
  537. ret = KP_TRY (mul_##s1##s2 (interp, x, y)); \
  538. return (ret); \
  539. case MIX (typecode::t2, typecode::t1): \
  540. ret = KP_TRY (mul_##s1##s2 (interp, y, x)); \
  541. return (ret)
  542. DISPATCH_1 (INT, i);
  543. DISPATCH_2 (INT, BIGINT, i, I);
  544. DISPATCH_2 (INT, FLOAT, i, f);
  545. DISPATCH_2 (INT, BIGFLOAT, i, F);
  546. DISPATCH_2 (INT, CHAR, i, c);
  547. DISPATCH_2 (INT, ARRAY, i, a);
  548. DISPATCH_2 (INT, BVECTOR, i, b);
  549. DISPATCH_2 (INT, STR, i, s);
  550. DISPATCH_1 (BIGINT, I);
  551. DISPATCH_2 (BIGINT, FLOAT, I, f);
  552. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  553. DISPATCH_1 (FLOAT, f);
  554. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  555. DISPATCH_1 (BIGFLOAT, F);
  556. default:
  557. return (UNBOUND);
  558. }
  559. #undef DISPATCH_1
  560. #undef DISPATCH_2
  561. }
  562. result<object> mul (interpreter *interp, object x, object y)
  563. {
  564. return (call_binary (interp, x, y, mul_helper, "g-mul"));
  565. }
  566. static result<object>
  567. div_helper (interpreter *interp, object x, object y)
  568. {
  569. object ret;
  570. switch (MIX (itype (x), itype (y)))
  571. {
  572. #define DISPATCH_1(type, suffix) \
  573. case MIX (typecode::type, typecode::type): \
  574. ret = KP_TRY (div_##suffix##suffix (interp, x, y)); \
  575. return (ret)
  576. #define DISPATCH_2(t1, t2, s1, s2) \
  577. case MIX (typecode::t1, typecode::t2): \
  578. ret = KP_TRY (div_##s1##s2 (interp, x, y)); \
  579. return (ret); \
  580. case MIX (typecode::t2, typecode::t1): \
  581. ret = KP_TRY (div_##s2##s1 (interp, x, y)); \
  582. return (ret)
  583. DISPATCH_1 (INT, i);
  584. DISPATCH_2 (INT, BIGINT, i, I);
  585. DISPATCH_2 (INT, FLOAT, i, f);
  586. DISPATCH_2 (INT, BIGFLOAT, i, F);
  587. DISPATCH_1 (BIGINT, I);
  588. DISPATCH_2 (BIGINT, FLOAT, I, f);
  589. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  590. DISPATCH_1 (FLOAT, f);
  591. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  592. DISPATCH_1 (BIGFLOAT, F);
  593. default:
  594. return (UNBOUND);
  595. }
  596. #undef DISPATCH_1
  597. #undef DISPATCH_2
  598. }
  599. result<object> div (interpreter *interp, object x, object y)
  600. {
  601. return (call_binary (interp, x, y, div_helper, "g-div"));
  602. }
  603. result<object> modulo (interpreter *interp, object x, object y)
  604. {
  605. object ret;
  606. switch (MIX (itype (x), itype (y)))
  607. {
  608. #define DISPATCH_1(type, suffix) \
  609. case MIX (typecode::type, typecode::type): \
  610. ret = KP_TRY (mod_##suffix##suffix (interp, x, y)); \
  611. return (ret)
  612. #define DISPATCH_2(t1, t2, s1, s2) \
  613. case MIX (typecode::t1, typecode::t2): \
  614. ret = KP_TRY (mod_##s1##s2 (interp, x, y)); \
  615. return (ret); \
  616. case MIX (typecode::t2, typecode::t1): \
  617. ret = KP_TRY (mod_##s2##s1 (interp, x, y)); \
  618. return (ret)
  619. DISPATCH_1 (INT, i);
  620. DISPATCH_2 (INT, BIGINT, i, I);
  621. DISPATCH_2 (INT, FLOAT, i, f);
  622. DISPATCH_2 (INT, BIGFLOAT, i, F);
  623. DISPATCH_1 (BIGINT, I);
  624. DISPATCH_2 (BIGINT, FLOAT, I, f);
  625. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  626. DISPATCH_1 (FLOAT, f);
  627. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  628. DISPATCH_1 (BIGFLOAT, F);
  629. default:
  630. return (invalid_arg (interp, "mod"));
  631. }
  632. #undef DISPATCH_1
  633. #undef DISPATCH_2
  634. }
  635. result<bool> equal (interpreter *interp, object x, object y)
  636. {
  637. if (x == y)
  638. // Identical objects compare equal iff they're not NaN or INF.
  639. return (x != FLT_QNAN && x != FLT_PINF && x != FLT_NINF);
  640. #define eq_ii(interp, x, y) false
  641. #define eq_cc(interp, x, y) false
  642. bool ret = false;
  643. switch (MIX (itype (x), itype (y)))
  644. {
  645. #define DISPATCH_1(type, suffix) \
  646. case MIX (typecode::type, typecode::type): \
  647. ret = KP_TRY (eq_##suffix##suffix (interp, x, y)); \
  648. return (ret)
  649. #define DISPATCH_2(t1, t2, s1, s2) \
  650. case MIX (typecode::t1, typecode::t2): \
  651. ret = KP_TRY (eq_##s1##s2 (interp, x, y)); \
  652. return (ret); \
  653. case MIX (typecode::t2, typecode::t1): \
  654. ret = KP_TRY (eq_##s1##s2 (interp, y, x)); \
  655. return (ret)
  656. DISPATCH_1 (INT, i);
  657. DISPATCH_2 (INT, FLOAT, i, f);
  658. DISPATCH_1 (BIGINT, I);
  659. DISPATCH_2 (BIGINT, FLOAT, I, f);
  660. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  661. DISPATCH_1 (FLOAT, f);
  662. DISPATCH_1 (BIGFLOAT, F);
  663. DISPATCH_1 (BVECTOR, b);
  664. DISPATCH_2 (BVECTOR, STR, b, s);
  665. DISPATCH_1 (STR, s);
  666. DISPATCH_1 (ARRAY, a);
  667. DISPATCH_1 (CONS, L);
  668. DISPATCH_1 (CHAR, c);
  669. DISPATCH_1 (FCT, x);
  670. default:
  671. // XXX: Custom types.
  672. return (invalid_arg (interp, "equal"));
  673. }
  674. #undef eq_ii
  675. #undef eq_cc
  676. #undef DISPATCH_1
  677. #undef DISPATCH_2
  678. }
  679. result<int> xcmp (interpreter *interp, object x, object y)
  680. {
  681. if (x == y)
  682. return (x != FLT_QNAN ? 0 : -1);
  683. int ret;
  684. switch (MIX (itype (x), itype (y)))
  685. {
  686. #define DISPATCH_1(type, suffix) \
  687. case MIX (typecode::type, typecode::type): \
  688. ret = KP_TRY (cmp_##suffix##suffix (interp, x, y)); \
  689. return (ret)
  690. #define DISPATCH_2(t1, t2, s1, s2) \
  691. case MIX (typecode::t1, typecode::t2): \
  692. ret = KP_TRY (cmp_##s1##s2 (interp, x, y)); \
  693. return (ret); \
  694. case MIX (typecode::t2, typecode::t1): \
  695. ret = KP_TRY (cmp_##s1##s2 (interp, y, x)); \
  696. return (-ret)
  697. DISPATCH_1 (INT, i);
  698. DISPATCH_2 (INT, BIGINT, i, I);
  699. DISPATCH_2 (INT, FLOAT, i, f);
  700. DISPATCH_2 (INT, BIGFLOAT, i, F);
  701. DISPATCH_1 (BIGINT, I);
  702. DISPATCH_2 (BIGINT, FLOAT, I, f);
  703. DISPATCH_2 (BIGINT, BIGFLOAT, I, F);
  704. DISPATCH_1 (FLOAT, f);
  705. DISPATCH_2 (FLOAT, BIGFLOAT, f, F);
  706. DISPATCH_1 (BIGFLOAT, F);
  707. DISPATCH_1 (ARRAY, a);
  708. DISPATCH_1 (CONS, L);
  709. DISPATCH_1 (BVECTOR, b);
  710. DISPATCH_2 (BVECTOR, STR, b, s);
  711. DISPATCH_1 (STR, s);
  712. default:
  713. // XXX: Custom types.
  714. return (x < y ? -1 : 1);
  715. }
  716. #undef DISPATCH_1
  717. #undef DISPATCH_2
  718. }
  719. #define DEFBUILTIN(name) \
  720. result<object> name (interpreter *interp, object *argv, int argc)
  721. // (car arg)
  722. static DEFBUILTIN (car_fct)
  723. {
  724. cons *cnp = as<cons> (*argv);
  725. if (!cnp)
  726. return (interp->raise ("type-error", "car: value is not a cons"));
  727. kp_return (cnp->car);
  728. }
  729. // (cdr arg)
  730. static DEFBUILTIN (cdr_fct)
  731. {
  732. cons *cnp = as<cons> (*argv);
  733. if (!cnp)
  734. return (interp->raise ("type-error", "cdr: value is not a cons"));
  735. kp_return (cnp->cdr);
  736. }
  737. // (cons arg1 arg2)
  738. static DEFBUILTIN (cons_fct)
  739. {
  740. return (cons::make (interp, argv[0], argv[1]));
  741. }
  742. // (list [...args])
  743. DEFBUILTIN (list_fct)
  744. {
  745. if (argc == 0)
  746. kp_return (NIL);
  747. KP_VTRY (alloc_cons (interp, argc, argv, nullptr));
  748. kp_return (interp->alval);
  749. }
  750. // (list* arg1 [...args])
  751. DEFBUILTIN (list_star)
  752. {
  753. if (argc == 1)
  754. kp_return (*argv);
  755. object *tail, lst = KP_TRY (alloc_cons (interp, argc - 1, argv, &tail));
  756. *tail = argv[argc - 1];
  757. kp_return (lst);
  758. }
  759. // (+ [...args])
  760. DEFBUILTIN (add_fct)
  761. {
  762. if (argc == 0)
  763. kp_return (fixint (0));
  764. else if (argc == 1)
  765. {
  766. object tmp = *argv;
  767. switch (itype (tmp))
  768. {
  769. case typecode::INT:
  770. case typecode::FLOAT:
  771. case typecode::BIGINT:
  772. case typecode::BIGFLOAT:
  773. kp_return (tmp);
  774. default:
  775. // XXX: Custom types.
  776. return (invalid_arg (interp, "+"));
  777. }
  778. }
  779. valref rv (interp, *argv);
  780. for (int i = 1; i < argc; ++i)
  781. { *rv = KP_TRY (add (interp, *rv, argv[i])); }
  782. kp_return (*rv);
  783. }
  784. // (- arg1 [...args])
  785. DEFBUILTIN (sub_fct)
  786. {
  787. if (argc == 1)
  788. {
  789. object tmp = *argv;
  790. switch (itype (tmp))
  791. {
  792. case typecode::INT:
  793. return (neg_i (interp, tmp));
  794. #ifdef KP_ARCH_WIDE
  795. case typecode::BIGINT:
  796. case typecode::FLOAT:
  797. case typecode::BIGFLOAT:
  798. kp_return (tmp ^ SIGN_BIT);
  799. #else
  800. case typecode::BIGINT:
  801. return (neg_I (interp, tmp));
  802. case typecode::FLOAT:
  803. return (neg_f (interp, tmp));
  804. case typecode::BIGFLOAT:
  805. return (neg_F (interp, tmp));
  806. #endif
  807. // XXX: Custom types.
  808. default:
  809. return (invalid_arg (interp, "-"));
  810. }
  811. }
  812. valref rv (interp, *argv);
  813. for (int i = 1; i < argc; ++i)
  814. { *rv = KP_TRY (sub (interp, *rv, argv[i])); }
  815. kp_return (*rv);
  816. }
  817. // (* [...args])
  818. DEFBUILTIN (mul_fct)
  819. {
  820. if (argc == 0)
  821. kp_return (fixint (1));
  822. valref rv (interp, *argv);
  823. for (int i = 1; i < argc; ++i)
  824. { *rv = KP_TRY (mul (interp, *rv, argv[i])); }
  825. kp_return (*rv);
  826. }
  827. // (/ arg1 [...args])
  828. DEFBUILTIN (div_fct)
  829. {
  830. if (argc == 1)
  831. return (div (interp, fixint (1), *argv));
  832. valref rv (interp, *argv);
  833. for (int i = 1; i < argc; ++i)
  834. { *rv = KP_TRY (div (interp, *rv, argv[i])); }
  835. kp_return (*rv);
  836. }
  837. // (lsh x shift)
  838. DEFBUILTIN (lsh_fct)
  839. {
  840. switch (itype (*argv))
  841. {
  842. #define DISPATCH(type, suffix) \
  843. case typecode::type: \
  844. return (lsh_##suffix##i (interp, argv[0], argv[1]))
  845. DISPATCH (INT, i);
  846. DISPATCH (BIGINT, I);
  847. DISPATCH (FLOAT, f);
  848. DISPATCH (BIGFLOAT, F);
  849. default:
  850. if (bigint_p (argv[1]))
  851. return (interp->raise ("arith-error", "shift overflow"));
  852. return (invalid_arg (interp, "lsh"));
  853. }
  854. #undef DISPATCH
  855. }
  856. // (rsh x shift)
  857. DEFBUILTIN (rsh_fct)
  858. {
  859. switch (itype (*argv))
  860. {
  861. #define DISPATCH(type, suffix) \
  862. case typecode::type: \
  863. return (rsh_##suffix##i (interp, argv[0], argv[1]))
  864. DISPATCH (INT, i);
  865. DISPATCH (BIGINT, I);
  866. DISPATCH (FLOAT, f);
  867. DISPATCH (BIGFLOAT, F);
  868. default:
  869. if (bigint_p (argv[1]))
  870. return (interp->raise ("arith-error", "shift overflow"));
  871. return (invalid_arg (interp, "rsh"));
  872. }
  873. #undef DISPATCH
  874. }
  875. // (< arg1 [...args])
  876. DEFBUILTIN (lt_fct)
  877. {
  878. for (int i = 0; i < argc - 1; ++i)
  879. {
  880. int c = KP_TRY (xcmp (interp, argv[i], argv[i + 1]));
  881. if (c >= 0)
  882. kp_return (NIL);
  883. }
  884. kp_return (symbol::t);
  885. }
  886. // (> arg1 [...args])
  887. DEFBUILTIN (gt_fct)
  888. {
  889. for (int i = 0; i < argc - 1; ++i)
  890. {
  891. int c = KP_TRY (xcmp (interp, argv[i], argv[i + 1]));
  892. if (c <= 0)
  893. kp_return (NIL);
  894. }
  895. kp_return (symbol::t);
  896. }
  897. // (<= arg1 [...args])
  898. DEFBUILTIN (lte_fct)
  899. {
  900. for (int i = 0; i < argc - 1; ++i)
  901. {
  902. int c = KP_TRY (xcmp (interp, argv[i], argv[i + 1]));
  903. if (c > 0)
  904. kp_return (NIL);
  905. }
  906. kp_return (symbol::t);
  907. }
  908. // (>= arg1 [...args])
  909. DEFBUILTIN (gte_fct)
  910. {
  911. for (int i = 0; i < argc - 1; ++i)
  912. {
  913. int c = KP_TRY (xcmp (interp, argv[i], argv[i + 1]));
  914. if (c < 0)
  915. kp_return (NIL);
  916. }
  917. kp_return (symbol::t);
  918. }
  919. // (!= arg1 [...args])
  920. DEFBUILTIN (ne_fct)
  921. {
  922. for (int i = 0; i < argc - 1; ++i)
  923. {
  924. int c = KP_TRY (xcmp (interp, argv[i], argv[i + 1]));
  925. if (c == 0)
  926. kp_return (NIL);
  927. }
  928. kp_return (symbol::t);
  929. }
  930. // (nputcar val lst)
  931. static DEFBUILTIN (nputcar_fct)
  932. {
  933. cons *cnp = as<cons> (argv[1]);
  934. if (!cnp || cnp == as_cons (NIL))
  935. return (interp->raise ("type-error", "value is not a cons"));
  936. return (nputcar (interp, cnp->as_obj (), argv[0]));
  937. }
  938. // (nputcdr val lst)
  939. static DEFBUILTIN (nputcdr_fct)
  940. {
  941. cons *cnp = as<cons> (argv[1]);
  942. if (!cnp || cnp == as_cons (NIL))
  943. return (interp->raise ("type-error", "value is not a cons"));
  944. return (nputcdr (interp, cnp->as_obj (), argv[0]));
  945. }
  946. // (is x y)
  947. static DEFBUILTIN (is_fct)
  948. {
  949. kp_return (argv[0] == argv[1] ? symbol::t : NIL);
  950. }
  951. // (= x y [...args])
  952. static DEFBUILTIN (eq_fct)
  953. {
  954. for (int i = 0; i < argc - 1; ++i)
  955. {
  956. bool rv = KP_TRY (equal (interp, argv[i], argv[i + 1]));
  957. if (!rv)
  958. kp_return (NIL);
  959. }
  960. kp_return (symbol::t);
  961. }
  962. // (array [...args])
  963. DEFBUILTIN (array_fct)
  964. {
  965. object ret = KP_TRY (alloc_array (interp, argc));
  966. copy_objs (&xaref(ret, 0), argv, argc);
  967. kp_return (ret);
  968. }
  969. // (tuple test_fn [...args])
  970. DEFBUILTIN (tuple_fct)
  971. {
  972. valref ret = KP_TRY (alloc_tuple (interp, *argv));
  973. for (int i = 1; i < argc; ++i)
  974. KP_VTRY (tuple_put (interp, *ret, argv[i], false));
  975. kp_return (*ret);
  976. }
  977. // (%putd symbol code definition)
  978. DEFBUILTIN (p_putd)
  979. {
  980. if (!fixint_p (argv[1]))
  981. return (interp->raise ("type-error", "second argument must be an integer"));
  982. else if (!symbol_p (*argv))
  983. return (interp->raise ("type-error", "first argument must be a symbol"));
  984. else if (as_symbol(*argv)->flagged_p (FLAGS_CONST))
  985. return (interp->raise ("const-error", "cannot assign to a constant"));
  986. uint32_t eflags = 0;
  987. int type = as_int (argv[1]);
  988. switch (type)
  989. {
  990. case 0: // function.
  991. case 5: // regular symbol.
  992. break;
  993. case 6: // literal.
  994. eflags |= symbol::literal_flag;
  995. // FALLTHROUGH.
  996. case 1: // constant.
  997. eflags |= FLAGS_CONST;
  998. break;
  999. case 2: // special variable.
  1000. eflags |= symbol::special_flag;
  1001. break;
  1002. case 3: // macro.
  1003. eflags |= symbol::ctv_flag;
  1004. break;
  1005. case 4: // alias.
  1006. eflags |= symbol::alias_flag;
  1007. break;
  1008. default:
  1009. return (interp->raise ("arg-error", "invalid code specified"));
  1010. }
  1011. if (type == 0 || type == 3)
  1012. {
  1013. function *fp = as<function> (argv[2]);
  1014. if (!fp)
  1015. return (interp->raise ("type-error", "argument must be a function"));
  1016. if (nil_p (fp->name))
  1017. // Mutate the argument and set the name.
  1018. fp->name = *argv;
  1019. else
  1020. { // Copy the function with the new name.
  1021. KP_VTRY (alloc_fct (interp));
  1022. function *f2 = as_fct (interp->alval);
  1023. fp->copy_into (f2);
  1024. f2->name = *argv;
  1025. argv[2] = f2->as_obj ();
  1026. }
  1027. }
  1028. symval(*argv) = argv[2];
  1029. if (eflags)
  1030. {
  1031. symbol *sp = as_symbol (*argv);
  1032. sp->cas_flag (symbol::special_flag | symbol::ctv_flag |
  1033. symbol::alias_flag, eflags);
  1034. if ((eflags & symbol::special_flag) && !sp->tl_idx)
  1035. { sp->tl_idx = KP_TRY (symbol::alloc_tl_idx (interp)); }
  1036. }
  1037. kp_return (argv[2]);
  1038. }
  1039. static inline object
  1040. strm_out (interpreter *interp)
  1041. {
  1042. object obj = find_sym (interp, "*out*", 5);
  1043. return (symbol_p (obj) ? symval (interp, obj) : out_stream);
  1044. }
  1045. static result<object>
  1046. print_helper (interpreter *interp, object strm,
  1047. object *argv, int argc, bool nl)
  1048. {
  1049. stream *out = as<stream> (strm);
  1050. stream_guard sg { interp, nullptr };
  1051. auto lg = KP_TRY (lock_guard::make (interp));
  1052. if (out)
  1053. ;
  1054. else if (string *sp = as<string> (strm))
  1055. {
  1056. *sg = out = KP_TRY (strstream (interp, sp->as_obj (),
  1057. STRM_WRITE | STRM_APP | STRM_NOLOCK));
  1058. }
  1059. else
  1060. return (interp->raise ("type-error",
  1061. "output argument must be a string or stream"));
  1062. if (!singlethr_p () && !sg.strmp)
  1063. KP_VTRY (lg.set (as_lock (out->ilock)));
  1064. io_info info { io_info::FLG_RAW };
  1065. interp->retval = symbol::t;
  1066. for (int i = 0; i < argc; ++i)
  1067. {
  1068. int64_t rv = KP_TRY (xwrite (interp, out, argv[i], info));
  1069. if (rv < 0)
  1070. {
  1071. interp->retval = NIL;
  1072. break;
  1073. }
  1074. }
  1075. if (nl && !nil_p (interp->retval))
  1076. {
  1077. int b = KP_TRY (out->putb (interp, '\n'));
  1078. if (b < 0)
  1079. interp->retval = NIL;
  1080. }
  1081. if (sg.strmp)
  1082. KP_VTRY (sstream_get (interp, sg.strmp));
  1083. return (interp->retval);
  1084. }
  1085. // (print-to stream arg1 [...args])
  1086. static DEFBUILTIN (print_to_fct)
  1087. {
  1088. return (print_helper (interp, *argv, argv + 1, argc - 1, false));
  1089. }
  1090. // (say-to stream [...args])
  1091. static DEFBUILTIN (say_to_fct)
  1092. {
  1093. return (print_helper (interp, *argv, argv + 1, argc - 1, true));
  1094. }
  1095. // (print arg1 [...args])
  1096. static DEFBUILTIN (print_fct)
  1097. {
  1098. return (print_helper (interp, strm_out (interp), argv, argc, false));
  1099. }
  1100. // (say [...args])
  1101. static DEFBUILTIN (say_fct)
  1102. {
  1103. return (print_helper (interp, strm_out (interp), argv, argc, true));
  1104. }
  1105. // (copy obj [deep])
  1106. static DEFBUILTIN (copy_fct)
  1107. {
  1108. return (copy (interp, *argv, argc == 2 && !nil_p (argv[1])));
  1109. }
  1110. // (reverse obj)
  1111. DEFBUILTIN (reverse_fct)
  1112. {
  1113. object ret;
  1114. switch (itype (*argv))
  1115. {
  1116. #define DISPATCH(type, suffix) \
  1117. case typecode::type: \
  1118. ret = KP_TRY (reverse_##suffix (interp, *argv)); \
  1119. return (ret)
  1120. DISPATCH (ARRAY, a);
  1121. DISPATCH (BVECTOR, b);
  1122. DISPATCH (STR, s);
  1123. DISPATCH (CONS, L);
  1124. default:
  1125. return (invalid_arg (interp, "reverse"));
  1126. #undef DISPATCH
  1127. }
  1128. }
  1129. // (nreverse obj)
  1130. DEFBUILTIN (nreverse_fct)
  1131. {
  1132. object ret;
  1133. switch (itype (*argv))
  1134. {
  1135. #define DISPATCH(type, suffix) \
  1136. case typecode::type: \
  1137. ret = KP_TRY (nreverse_##suffix (interp, *argv)); \
  1138. return (ret)
  1139. DISPATCH (ARRAY, a);
  1140. DISPATCH (BVECTOR, b);
  1141. DISPATCH (CONS, L);
  1142. default:
  1143. return (invalid_arg (interp, "nreverse"));
  1144. #undef DISPATCH
  1145. }
  1146. }
  1147. // (nput sequence key value)
  1148. DEFBUILTIN (nput_fct)
  1149. {
  1150. object ret;
  1151. switch (itype (*argv))
  1152. {
  1153. #define DISPATCH(type, suffix) \
  1154. case typecode::type: \
  1155. ret = KP_TRY (nput_##suffix (interp, argv[0], argv[1], argv[2])); \
  1156. return (ret)
  1157. DISPATCH (ARRAY, a);
  1158. DISPATCH (BVECTOR, b);
  1159. DISPATCH (CONS, L);
  1160. DISPATCH (TABLE, u);
  1161. DISPATCH (TUPLE, o);
  1162. DISPATCH (PKG, P);
  1163. DISPATCH (INSTANCE, w);
  1164. default:
  1165. return (invalid_arg (interp, "nput"));
  1166. #undef DISPATCH
  1167. }
  1168. }
  1169. // (disasm function [stream])
  1170. static DEFBUILTIN (disasm_fct)
  1171. {
  1172. object out;
  1173. bool allocated = false;
  1174. if (argc < 2)
  1175. {
  1176. out = strm_out (interp);
  1177. if (str_p (out))
  1178. {
  1179. auto tmp = KP_TRY (strstream (interp, out, STRM_WRITE |
  1180. STRM_APP | STRM_NOLOCK));
  1181. out = tmp->as_obj ();
  1182. allocated = true;
  1183. }
  1184. }
  1185. else
  1186. out = argv[1];
  1187. KP_VTRY (disasm (interp, *argv, out));
  1188. if (allocated)
  1189. {
  1190. stream *ostr = as_stream (out);
  1191. KP_VTRY (sstream_get (interp, ostr));
  1192. deref (ostr->close (interp));
  1193. }
  1194. else
  1195. interp->retval = symbol::t;
  1196. return (interp->retval);
  1197. }
  1198. // (not obj)
  1199. static DEFBUILTIN (not_fct)
  1200. {
  1201. kp_return (nil_p (*argv) ? *argv : symbol::t);
  1202. }
  1203. // (len obj)
  1204. static DEFBUILTIN (len_fct)
  1205. {
  1206. interp->retval = KP_TRY (length (interp, *argv));
  1207. return (interp->retval);
  1208. }
  1209. struct custom_comparator : public comparator
  1210. {
  1211. object cb;
  1212. custom_comparator (interpreter *ip, object obj) : comparator (ip), cb (obj)
  1213. {
  1214. }
  1215. result<bool> operator() (object x, object y)
  1216. {
  1217. KP_VTRY (this->interp->growstk (3));
  1218. *this->interp->stkend++ = this->cb;
  1219. *this->interp->stkend++ = x;
  1220. *this->interp->stkend++ = y;
  1221. KP_VTRY (call_n (this->interp, 2));
  1222. return (interp->retval != NIL);
  1223. }
  1224. };
  1225. // (nsort seq [comparison])
  1226. DEFBUILTIN (nsort_fct)
  1227. {
  1228. lazy<comparator> c1;
  1229. lazy<custom_comparator> c2;
  1230. comparator *cx;
  1231. if (argc == 1)
  1232. cx = new (c1.ptr ()) comparator (interp);
  1233. else
  1234. cx = new (c2.ptr ()) custom_comparator (interp, argv[1]);
  1235. switch (itype (*argv))
  1236. {
  1237. case typecode::CONS:
  1238. KP_VTRY (nsort_L (interp, *argv, *cx));
  1239. case typecode::ARRAY:
  1240. KP_VTRY (nsort_a (interp, *argv, *cx));
  1241. case typecode::TUPLE:
  1242. kp_return (*argv);
  1243. default:
  1244. return (invalid_arg (interp, "nsort"));
  1245. }
  1246. return (interp->retval);
  1247. }
  1248. // (subseq seq arg-1 [arg-2])
  1249. DEFBUILTIN (subseq_fct)
  1250. {
  1251. object i2 = argc == 3 ? argv[2] : UNBOUND, ret;
  1252. switch (itype (*argv))
  1253. {
  1254. #define DISPATCH(type, suffix) \
  1255. case typecode::type: \
  1256. ret = KP_TRY (subseq_##suffix (interp, argv[0], argv[1], i2)); \
  1257. return (ret)
  1258. DISPATCH (CONS, L);
  1259. DISPATCH (ARRAY, a);
  1260. DISPATCH (BVECTOR, b);
  1261. DISPATCH (STR, s);
  1262. default:
  1263. return (invalid_arg (interp, "subseq"));
  1264. #undef DISPATCH
  1265. }
  1266. }
  1267. // (concat [...args])
  1268. DEFBUILTIN (concat_fct)
  1269. {
  1270. if (argc == 0)
  1271. kp_return (NIL);
  1272. object ret;
  1273. switch (itype (*argv))
  1274. {
  1275. #define DISPATCH(type, suffix) \
  1276. case typecode::type: \
  1277. ret = KP_TRY (concat_##suffix (interp, argv, argc)); \
  1278. return (ret)
  1279. DISPATCH (CONS, L);
  1280. DISPATCH (ARRAY, a);
  1281. DISPATCH (BVECTOR, b);
  1282. DISPATCH (STR, s);
  1283. default:
  1284. return (invalid_arg (interp, "concat"));
  1285. #undef DISPATCH
  1286. }
  1287. }
  1288. // (nrevconc obj)
  1289. static DEFBUILTIN (nrevconc_fct)
  1290. {
  1291. return (nrevconc (interp, *argv, argv[1]));
  1292. }
  1293. // (load path)
  1294. DEFBUILTIN (load_fct)
  1295. {
  1296. object path = *argv;
  1297. if (!str_p (path))
  1298. return (interp->raise ("type-error", "path must be a string"));
  1299. auto fptr = KP_TRY (fstream_open (interp, str_cdata (path), "r"));
  1300. if (!fptr)
  1301. // XXX: Report why the file couldn't be opened.
  1302. return (interp->raise ("load-error",
  1303. KP_SPRINTF (interp,
  1304. "could not open file '%Q'", path)));
  1305. stream_guard sg { interp, fptr };
  1306. reader rd (interp, sg.as_obj ());
  1307. while (true)
  1308. {
  1309. object expr = KP_TRY (rd.read_sexpr ());
  1310. if (expr == EOS)
  1311. break;
  1312. KP_VTRY (eval (interp, expr));
  1313. }
  1314. kp_return (symbol::t);
  1315. }
  1316. // (macroexp-1 expr)
  1317. static DEFBUILTIN (macroexp_1_fct)
  1318. {
  1319. return (macroexp_1 (interp, *argv));
  1320. }
  1321. // (macroexp expr)
  1322. static DEFBUILTIN (macroexp_fct)
  1323. {
  1324. return (macroexp (interp, *argv));
  1325. }
  1326. // (coro-val coroutine)
  1327. static DEFBUILTIN (coro_val)
  1328. {
  1329. auto cnp = as<coroutine> (*argv);
  1330. if (!cnp)
  1331. return (interp->raise ("type-error", "argument must be a coroutine"));
  1332. kp_return (cnp->value);
  1333. }
  1334. // (symname symbol)
  1335. static DEFBUILTIN (symname_fct)
  1336. {
  1337. symbol *sym = as<symbol> (*argv);
  1338. if (!sym)
  1339. return (interp->raise ("type-error", "argument must be a symbol"));
  1340. kp_return (sym->name);
  1341. }
  1342. // (symval symbol [default-value])
  1343. static DEFBUILTIN (symval_fct)
  1344. {
  1345. symbol *sym = as<symbol> (*argv);
  1346. if (!sym)
  1347. return (interp->raise ("type-error", "first argument must be a symbol"));
  1348. object ret = sym->value;
  1349. if (ret != UNBOUND)
  1350. kp_return (ret);
  1351. else if (argc == 2)
  1352. kp_return (argv[1]);
  1353. else
  1354. return (interp->raise ("unbound-error",
  1355. KP_SPRINTF (interp, "symbol %Q has no value",
  1356. sym->as_obj ())));
  1357. }
  1358. // (sympkg symbol)
  1359. static DEFBUILTIN (sympkg_fct)
  1360. {
  1361. symbol *sym = as<symbol> (*argv);
  1362. if (!sym)
  1363. return (interp->raise ("type-error", "argument must be a symbol or nil"));
  1364. kp_return (sym->pkg);
  1365. }
  1366. // (%use name (:as alias) (:pull (:all symbols...)))
  1367. static DEFBUILTIN (p_use_fct)
  1368. {
  1369. object a1 = argc < 2 ? NIL : argv[1];
  1370. object a2 = argc < 3 ? NIL : argv[2];
  1371. return (pull_pkg (interp, *argv, a1, a2));
  1372. }
  1373. // (%gc)
  1374. static DEFBUILTIN (p_gc)
  1375. {
  1376. KP_VTRY (gc (false));
  1377. kp_return (NIL);
  1378. }
  1379. // (%iter sequence token [advance])
  1380. static DEFBUILTIN (p_iter)
  1381. {
  1382. object token = argc < 2 ? UNBOUND : argv[1], ret;
  1383. bool adv = argc == 3 && !nil_p (argv[2]);
  1384. #define DISPATCH(type, suffix) \
  1385. case typecode::type: \
  1386. ret = KP_TRY (iter_##suffix (interp, *argv, token, adv)); \
  1387. return (ret)
  1388. switch (itype (*argv))
  1389. {
  1390. DISPATCH (ARRAY, a);
  1391. DISPATCH (CONS, L);
  1392. DISPATCH (BVECTOR, b);
  1393. DISPATCH (STR, s);
  1394. DISPATCH (TABLE, u);
  1395. DISPATCH (TUPLE, o);
  1396. default:
  1397. // XXX: Custom types
  1398. return (invalid_arg (interp, "%iter"));
  1399. }
  1400. #undef DISPATCH
  1401. }
  1402. // (macro-fct symbol)
  1403. static DEFBUILTIN (macro_fct)
  1404. {
  1405. object sym = *argv;
  1406. if (!symbol_p (sym))
  1407. return (interp->raise ("type-error", "argument must be a symbol"));
  1408. else if (!as_symbol(sym)->flagged_p (symbol::ctv_flag))
  1409. kp_return (NIL);
  1410. sym = symval (sym);
  1411. kp_return (fct_p (sym) ? sym : NIL);
  1412. }
  1413. // (nzap sequence key flags fn [...args])
  1414. DEFBUILTIN (nzap_fct)
  1415. {
  1416. uint32_t flags = (fixint_p (argv[2]) ? as_int (argv[2]) : 0) |
  1417. (singlethr_p () ? NZAP_NOMT : 0);
  1418. #define DISPATCH(type, suffix) \
  1419. case typecode::type: \
  1420. KP_VTRY (nzap_##suffix (interp, argv[0], argv[1], flags, \
  1421. argv[3], &argv[4], argc - 4)); \
  1422. return (interp->retval)
  1423. switch (itype (*argv))
  1424. {
  1425. DISPATCH (ARRAY, a);
  1426. DISPATCH (CONS, L);
  1427. DISPATCH (TABLE, u);
  1428. DISPATCH (TUPLE, o);
  1429. DISPATCH (PKG, P);
  1430. default:
  1431. return (invalid_arg (interp, "nzap"));
  1432. }
  1433. #undef DISPATCH
  1434. }
  1435. // (intern string [package])
  1436. static DEFBUILTIN (intern_fct)
  1437. {
  1438. string *name = as<string> (*argv);
  1439. if (!name)
  1440. return (interp->raise ("type-error", "first argument must be a string"));
  1441. package *p = nullptr;
  1442. if (argc == 1)
  1443. ;
  1444. else if (!(p = as<package> (argv[1])))
  1445. return (interp->raise ("type-error", "second argument must be a package"));
  1446. return (intern (interp, name, p));
  1447. }
  1448. // (fct-name function)
  1449. static DEFBUILTIN (fct_name_fct)
  1450. {
  1451. object fn = *argv;
  1452. if (!fct_p (fn))
  1453. return (interp->raise ("type-error", "argument must be a function"));
  1454. kp_return (fct_name (fn));
  1455. }
  1456. // (type object [parents slot-definitions])
  1457. static DEFBUILTIN (type_fct)
  1458. {
  1459. if (argc == 1)
  1460. kp_return (type (argv[0]));
  1461. else if (argc == 2)
  1462. return (type (interp, argv[0], argv[1], NIL));
  1463. else
  1464. return (type (interp, argv[0], argv[1], argv[2]));
  1465. }
  1466. // (make type [...args])
  1467. DEFBUILTIN (make_fct)
  1468. {
  1469. KP_VTRY (alloc_inst (interp, *argv, argv + 1, argc - 1));
  1470. kp_return (interp->alval);
  1471. }
  1472. // (isa object type1 [...types])
  1473. static DEFBUILTIN (isa_fct)
  1474. {
  1475. for (int i = 1; i < argc; ++i)
  1476. {
  1477. int rv = instanceof (*argv, argv[i]);
  1478. if (rv < 0)
  1479. return (interp->raise ("type-error", "argument must be a typespec"));
  1480. else if (rv)
  1481. kp_return (symbol::t);
  1482. }
  1483. kp_return (NIL);
  1484. }
  1485. // (%symtst symbol code)
  1486. static DEFBUILTIN (p_symtst)
  1487. {
  1488. int code;
  1489. const symbol *sym = as<symbol> (*argv);
  1490. if (!sym)
  1491. return (interp->raise ("type-error", "first argument must be a symbol"));
  1492. else if (!as<int> (argv[1], code))
  1493. return (interp->raise ("type-error", "second argument must be an integer"));
  1494. else if (code == 6)
  1495. kp_return (sym->value != UNBOUND &&
  1496. !sym->flagged_p (symbol::ctv_flag | symbol::alias_flag) ?
  1497. symbol::t : NIL);
  1498. const uint32_t flags[] =
  1499. {
  1500. FLAGS_CONST,
  1501. symbol::specform_flag,
  1502. symbol::special_flag,
  1503. symbol::ctv_flag,
  1504. symbol::alias_flag,
  1505. symbol::literal_flag
  1506. };
  1507. if (code < 0 || code >= (int)KP_NELEM (flags))
  1508. return (interp->raise ("arg-error", "invalid code"));
  1509. kp_return (sym->flagged_p (flags[code]) ? symbol::t : NIL);
  1510. }
  1511. // (last sequence)
  1512. static DEFBUILTIN (last_fct)
  1513. {
  1514. object obj = *argv, ret;
  1515. #define DISPATCH(type, suffix) \
  1516. case typecode::type: \
  1517. ret = KP_TRY (last_##suffix (interp, obj)); \
  1518. return (ret)
  1519. switch (itype (obj))
  1520. {
  1521. DISPATCH (CONS, L);
  1522. DISPATCH (ARRAY, a);
  1523. DISPATCH (BVECTOR, b);
  1524. DISPATCH (STR, s);
  1525. default:
  1526. return (invalid_arg (interp, "last"));
  1527. }
  1528. #undef DISPATCH
  1529. }
  1530. // (last-err [include-traceback])
  1531. static DEFBUILTIN (last_err_fct)
  1532. {
  1533. if (argc == 1 && !nil_p (*argv) && !nil_p (interp->last_err))
  1534. {
  1535. object ret = KP_TRY (alloc_cons (interp, 2));
  1536. xcar(ret) = interp->last_err;
  1537. xcar(xcdr (ret)) = interp->last_tb;
  1538. kp_return (ret);
  1539. }
  1540. kp_return (interp->last_err);
  1541. }
  1542. static DEFBUILTIN (find_fct)
  1543. {
  1544. object obj = argv[0], key = argv[1], ret;
  1545. object start = UNBOUND, end = UNBOUND, test = UNBOUND;
  1546. KP_VTRY (kwargs_parse (interp, argv + 2, argc - 2, "start", &start,
  1547. "end", &end, "test", &test));
  1548. #define DISPATCH(type, suffix) \
  1549. case typecode::type: \
  1550. ret = KP_TRY (find_##suffix (interp, obj, key, start, end, test)); \
  1551. return (ret)
  1552. switch (itype (obj))
  1553. {
  1554. DISPATCH (CONS, L);
  1555. DISPATCH (ARRAY, a);
  1556. DISPATCH (BVECTOR, b);
  1557. DISPATCH (STR, s);
  1558. default:
  1559. return (invalid_arg (interp, "find"));
  1560. }
  1561. #undef DISPATCH
  1562. }
  1563. // Names for the builtins.
  1564. static const char BUILTIN_NAMES[] =
  1565. "car\0"
  1566. "cdr\0"
  1567. "cons\0"
  1568. "list\0"
  1569. "list*\0"
  1570. "+\0-\0*\0/\0"
  1571. "<\0>\0<=\0>=\0!=\0"
  1572. "lsh\0"
  1573. "rsh\0"
  1574. "nputcar\0"
  1575. "nputcdr\0"
  1576. "apply\0"
  1577. "is\0=\0"
  1578. "array\0"
  1579. "table\0"
  1580. "tuple\0"
  1581. "%putd\0"
  1582. "gensym\0"
  1583. "print-to\0"
  1584. "say-to\0"
  1585. "print\0"
  1586. "say\0"
  1587. "copy\0"
  1588. "reverse\0"
  1589. "nreverse\0"
  1590. "nput\0"
  1591. "disasm\0"
  1592. "not\0"
  1593. "len\0"
  1594. "%fmt-str\0"
  1595. "nsort\0"
  1596. "subseq\0"
  1597. "concat\0"
  1598. "nconcat\0"
  1599. "nrevconc\0"
  1600. "load\0"
  1601. "macroexp-1\0"
  1602. "macroexp\0"
  1603. "coro-val\0"
  1604. "coro-next\0"
  1605. "symname\0"
  1606. "symval\0"
  1607. "sympkg\0"
  1608. "%use\0"
  1609. "%gc\0"
  1610. "%iter\0"
  1611. "exit\0"
  1612. "macro-fct\0"
  1613. "nzap\0"
  1614. "intern\0"
  1615. "fct-name\0"
  1616. "type\0"
  1617. "make\0"
  1618. "isa\0"
  1619. "%symtst\0"
  1620. "last\0"
  1621. "last-err\0"
  1622. "%meth-ctl\0"
  1623. "find\0"
  1624. ;
  1625. // List of builtins.
  1626. struct builtin_entry
  1627. {
  1628. native_function::fn_type fn;
  1629. int8_t min_argc;
  1630. int8_t max_argc;
  1631. };
  1632. static const builtin_entry BUILTINS[] =
  1633. {
  1634. { car_fct, 1, 1 },
  1635. { cdr_fct, 1, 1 },
  1636. { cons_fct, 2, 2 },
  1637. { list_fct, 0, -1 },
  1638. { list_star, 1, -1 },
  1639. { add_fct, 0, -1 },
  1640. { sub_fct, 1, -1 },
  1641. { mul_fct, 0, -1 },
  1642. { div_fct, 0, -1 },
  1643. { lt_fct, 1, -1 },
  1644. { gt_fct, 1, -1 },
  1645. { lte_fct, 1, -1 },
  1646. { gte_fct, 1, -1 },
  1647. { ne_fct, 1, -1 },
  1648. { lsh_fct, 2, 2 },
  1649. { rsh_fct, 2, 2 },
  1650. { nputcar_fct, 2, 2 },
  1651. { nputcdr_fct, 2, 2 },
  1652. { apply_fct, 2, -1 },
  1653. { is_fct, 2, 2 },
  1654. { eq_fct, 2, -1 },
  1655. { array_fct, 0, -1 },
  1656. { table_fct, 2, -1 },
  1657. { tuple_fct, 1, -1 },
  1658. { p_putd, 3, 3 },
  1659. { gensym, 0, 0 },
  1660. { print_to_fct, 2, -1 },
  1661. { say_to_fct, 1, -1 },
  1662. { print_fct, 1, -1 },
  1663. { say_fct, 0, -1 },
  1664. { copy_fct, 1, 2 },
  1665. { reverse_fct, 1, 1 },
  1666. { nreverse_fct, 1, 1 },
  1667. { nput_fct, 3, 3 },
  1668. { disasm_fct, 1, 2 },
  1669. { not_fct, 1, 1 },
  1670. { len_fct, 1, 1 },
  1671. { p_fmt_str, 1, -1 },
  1672. { nsort_fct, 1, 2 },
  1673. { subseq_fct, 2, 3 },
  1674. { concat_fct, 0, -1 },
  1675. { nconcat, 0, -1 },
  1676. { nrevconc_fct, 2, 2 },
  1677. { load_fct, 1, 1 },
  1678. { macroexp_1_fct, 1, 1 },
  1679. { macroexp_fct, 1, 1 },
  1680. { coro_val, 1, 1 },
  1681. { coro_next, 1, 2 },
  1682. { symname_fct, 1, 1 },
  1683. { symval_fct, 1, 2 },
  1684. { sympkg_fct, 1, 1 },
  1685. { p_use_fct, 1, 3 },
  1686. { p_gc, 0, -1 },
  1687. { p_iter, 1, 3 },
  1688. { exit_fct, 0, 1 },
  1689. { macro_fct, 1, 1 },
  1690. { nzap_fct, 4, -1 },
  1691. { intern_fct, 1, 2 },
  1692. { fct_name_fct, 1, 1 },
  1693. { type_fct, 1, 3 },
  1694. { make_fct, 1, -1 },
  1695. { isa_fct, 2, -1 },
  1696. { p_symtst, 2, 2 },
  1697. { last_fct, 1, 1 },
  1698. { last_err_fct, 0, 1 },
  1699. { p_meth_ctl, 1, -1 },
  1700. { find_fct, 2, 6 },
  1701. };
  1702. static native_function global_builtins[KP_NELEM (BUILTINS)];
  1703. object symbol::fast_global_syms[KP_NELEM (BUILTINS) + symbol::N_SPECFORMS + 1];
  1704. indexer_t index_seq (object seq)
  1705. {
  1706. switch (itype (seq))
  1707. {
  1708. case typecode::CONS:
  1709. return (get_L);
  1710. case typecode::ARRAY:
  1711. return (get_a);
  1712. case typecode::BVECTOR:
  1713. return (get_b);
  1714. case typecode::STR:
  1715. return (get_s);
  1716. case typecode::TABLE:
  1717. return (get_u);
  1718. case typecode::TUPLE:
  1719. return (get_o);
  1720. case typecode::PKG:
  1721. return (get_P);
  1722. case typecode::INSTANCE:
  1723. return (get_w);
  1724. default:
  1725. return (nullptr);
  1726. }
  1727. }
  1728. builtin_iter::builtin_iter () : curp (BUILTIN_NAMES)
  1729. {
  1730. }
  1731. void builtin_iter::adv ()
  1732. {
  1733. this->curp += strlen (this->curp) + 1;
  1734. }
  1735. bool builtin_iter::valid () const
  1736. {
  1737. return (*this->curp != 0);
  1738. }
  1739. int builtin_idx (interpreter *interp, const char *name)
  1740. {
  1741. int ix = 0;
  1742. for (builtin_iter it; it.valid (); it.adv (), ++ix)
  1743. if (strcmp (it.name (), name) == 0)
  1744. return (ix + symbol::N_SPECFORMS);
  1745. return (-1);
  1746. }
  1747. object builtin_fct (interpreter *interp, const char *name)
  1748. {
  1749. int ix = builtin_idx (interp, name) - symbol::N_SPECFORMS;
  1750. return (ix < 0 ? UNBOUND : global_builtins[ix].as_obj ());
  1751. }
  1752. object builtin_fct (interpreter *interp, int ix)
  1753. {
  1754. return (ix < 0 || ix >= (int)KP_NELEM (BUILTINS) ?
  1755. UNBOUND : global_builtins[ix].as_obj ());
  1756. }
  1757. static int
  1758. do_init_builtins (interpreter *interp)
  1759. {
  1760. int ret = init_op::call_deps (interp, &init_symbols);
  1761. if (ret != init_op::result_ok)
  1762. return (ret);
  1763. int ix = 0;
  1764. for (builtin_iter it; it.valid (); it.adv (), ++ix)
  1765. {
  1766. auto *outp = ensure_mask (&global_builtins[ix]);
  1767. outp->vo_full = function_base::native_flag;
  1768. outp->vo_type = typecode::FCT;
  1769. outp->fct = BUILTINS[ix].fn;
  1770. outp->min_argc = BUILTINS[ix].min_argc;
  1771. outp->max_argc = BUILTINS[ix].max_argc;
  1772. auto rs = INTERN_N (it.name ());
  1773. if (rs.error_p ())
  1774. return (init_op::result_failed);
  1775. object sym = outp->name = *rs;
  1776. symval(sym) = outp->as_obj ();
  1777. symbol::fast_global_syms[ix + symbol::N_SPECFORMS] = sym;
  1778. }
  1779. // Mark the end of the builtin symbols.
  1780. symbol::fast_global_syms[KP_NELEM (BUILTINS) + symbol::N_SPECFORMS] = UNBOUND;
  1781. return (ret);
  1782. }
  1783. init_op init_builtins (do_init_builtins, "builtins");
  1784. #undef INTERN
  1785. #undef INTERN_N
  1786. KP_DECLS_END