The Sol Programming Language!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

builtins.c 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include "sol.h"
  6. // XXX hardcoded buffer sizes
  7. static char *_itoa(int i) {
  8. int n = 33;
  9. char *s = malloc(n);
  10. snprintf(s, n, "%d", i);
  11. return s;
  12. }
  13. static char *_ftoa(double f) {
  14. int n = 65;
  15. char *s = malloc(n);
  16. snprintf(s, n, "%f", f);
  17. return s;
  18. }
  19. sol_object_t *sol_f_not_impl(sol_state_t *state, sol_object_t *args) {
  20. return sol_set_error_string(state, "Undefined method");
  21. }
  22. sol_object_t *sol_f_default_cmp(sol_state_t *state, sol_object_t *args) {
  23. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  24. sol_object_t *res = sol_new_int(state, a!=b);
  25. sol_obj_free(a);
  26. sol_obj_free(b);
  27. return res;
  28. }
  29. sol_object_t *sol_f_no_op(sol_state_t *state, sol_object_t *args) {
  30. if(state) return sol_incref(state->None);
  31. return NULL;
  32. }
  33. sol_object_t *sol_f_toint(sol_state_t *state, sol_object_t *args) {
  34. sol_object_t *obj = sol_list_get_index(state, args, 0);
  35. sol_object_t *res = obj->ops->toint(state, args);
  36. sol_obj_free(obj);
  37. return res;
  38. }
  39. sol_object_t *sol_f_tofloat(sol_state_t *state, sol_object_t *args) {
  40. sol_object_t *obj = sol_list_get_index(state, args, 0);
  41. sol_object_t *res = obj->ops->tofloat(state, args);
  42. sol_obj_free(obj);
  43. return res;
  44. }
  45. sol_object_t *sol_f_tostring(sol_state_t *state, sol_object_t *args) {
  46. sol_object_t *obj = sol_list_get_index(state, args, 0);
  47. sol_object_t *res = obj->ops->tostring(state, args);
  48. sol_obj_free(obj);
  49. return res;
  50. }
  51. sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
  52. sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
  53. sol_object_t *ls = sol_new_list(state), *one = sol_new_int(state, 1);
  54. sol_object_t *res;
  55. sol_list_insert(state, fargs, 0, func);
  56. res = func->ops->call(state, fargs);
  57. sol_obj_free(func);
  58. sol_obj_free(fargs);
  59. if(sol_has_error(state)) {
  60. sol_clear_error(state);
  61. sol_object_t *err = sol_get_error(state);
  62. sol_object_t *zero = sol_new_int(state, 0);
  63. sol_obj_free(res);
  64. sol_obj_free(one);
  65. sol_list_insert(state, ls, 0, err);
  66. sol_obj_free(err);
  67. sol_list_insert(state, ls, 0, zero);
  68. sol_obj_free(zero);
  69. return ls;
  70. }
  71. sol_list_insert(state, ls, 0, res);
  72. sol_obj_free(res);
  73. sol_list_insert(state, ls, 0, one);
  74. sol_obj_free(one);
  75. return ls;
  76. }
  77. static char *sol_TypeNames[] = {"singlet", "integer", "float", "string", "list", "listcell", "map", "mapcell", "function", "cfunction", "cdata"};
  78. sol_object_t *sol_f_type(sol_state_t *state, sol_object_t *args) {
  79. sol_object_t *obj = sol_list_get_index(state, args, 0);
  80. sol_object_t *res = sol_new_string(state, sol_TypeNames[obj->type]);
  81. sol_obj_free(obj);
  82. return res;
  83. }
  84. sol_object_t *p_seen[1024] = {0};
  85. void ob_print(sol_object_t *obj) {
  86. sol_object_t *cur;
  87. int i;
  88. for(i=0; i<1024; i++) {
  89. if(!p_seen[i]) {
  90. p_seen[i] = obj;
  91. break;
  92. }
  93. if(p_seen[i] == obj) {
  94. printf("... (%p)", obj);
  95. return;
  96. }
  97. }
  98. switch(obj->type) {
  99. case SOL_SINGLET:
  100. printf("<Singlet>");
  101. break;
  102. case SOL_INTEGER:
  103. printf("%ld", obj->ival);
  104. break;
  105. case SOL_FLOAT:
  106. printf("%f", obj->fval);
  107. break;
  108. case SOL_STRING:
  109. printf("\"%s\"", obj->str);
  110. break;
  111. case SOL_LCELL:
  112. printf("<<");
  113. /* fall through */
  114. case SOL_LIST:
  115. printf("[");
  116. cur = obj;
  117. while(cur) {
  118. if(cur->lvalue) {
  119. ob_print(cur->lvalue);
  120. }
  121. if(cur->lnext) {
  122. printf(", ");
  123. }
  124. cur = cur->lnext;
  125. }
  126. printf("]");
  127. break;
  128. case SOL_MCELL:
  129. printf("<<");
  130. /* fall through */
  131. case SOL_MAP:
  132. printf("{");
  133. cur = obj;
  134. while(cur) {
  135. if(cur->mkey) {
  136. printf("[");
  137. ob_print(cur->mkey);
  138. printf("] = ");
  139. ob_print(cur->mval);
  140. }
  141. if(cur->mnext) printf(", ");
  142. cur = cur->mnext;
  143. }
  144. printf("}");
  145. break;
  146. case SOL_FUNCTION:
  147. if(obj->fname) {
  148. printf("<Function %s>", obj->fname);
  149. } else {
  150. printf("<Function>");
  151. }
  152. break;
  153. case SOL_CFUNCTION:
  154. printf("<CFunction>");
  155. break;
  156. case SOL_CDATA:
  157. printf("<CData>");
  158. break;
  159. }
  160. }
  161. sol_object_t *sol_f_prepr(sol_state_t *state, sol_object_t *args) {
  162. int i, sz = sol_list_len(state, args);
  163. sol_object_t *obj;
  164. for(i=0; i<1024; i++) p_seen[i] = NULL;
  165. for(i=0; i<sz; i++) {
  166. obj = sol_list_get_index(state, args, i);
  167. ob_print(obj);
  168. printf(" ");
  169. sol_obj_free(obj);
  170. }
  171. printf("\n");
  172. return sol_incref(state->None);
  173. }
  174. sol_object_t *sol_f_print(sol_state_t *state, sol_object_t *args) {
  175. int i, sz = sol_list_len(state, args);
  176. sol_object_t *obj;
  177. for(i=0; i<1024; i++) p_seen[i] = NULL;
  178. for(i=0; i<sz; i++) {
  179. obj = sol_list_get_index(state, args, i);
  180. if(sol_is_string(obj)) {
  181. printf("%s", obj->str);
  182. } else {
  183. ob_print(obj);
  184. }
  185. printf(" ");
  186. sol_obj_free(obj);
  187. }
  188. printf("\n");
  189. return sol_incref(state->None);
  190. }
  191. sol_object_t *sol_f_rawget(sol_state_t *state, sol_object_t *args) {
  192. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *res;
  193. if(!sol_is_map(obj)) return sol_set_error_string(state, "Rawset of non-map");
  194. key = sol_list_get_index(state, args, 1);
  195. res = sol_map_get(state, obj, key);
  196. sol_obj_free(key);
  197. sol_obj_free(obj);
  198. return sol_incref(state->None);
  199. }
  200. sol_object_t *sol_f_rawset(sol_state_t *state, sol_object_t *args) {
  201. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *val;
  202. if(!sol_is_map(obj)) return sol_set_error_string(state, "Rawset of non-map");
  203. key = sol_list_get_index(state, args, 1);
  204. val = sol_list_get_index(state, args, 2);
  205. sol_map_set(state, obj, key, val);
  206. sol_obj_free(val);
  207. sol_obj_free(key);
  208. sol_obj_free(obj);
  209. return sol_incref(state->None);
  210. }
  211. sol_object_t *sol_f_range(sol_state_t *state, sol_object_t *args) {
  212. sol_object_t *res = sol_new_list(state), *bound = sol_cast_int(state, sol_list_get_index(state, args, 0));
  213. int i;
  214. for(i=0; i<bound->ival; i++) {
  215. sol_list_insert(state, res, sol_list_len(state, res), sol_new_int(state, i));
  216. }
  217. sol_obj_free(bound);
  218. return res;
  219. }
  220. sol_object_t *sol_f_debug_getref(sol_state_t *state, sol_object_t *args) {
  221. sol_object_t *obj = sol_list_get_index(state, args, 0);
  222. sol_object_t *res = sol_new_int(state, obj->refcnt - 2); // NB: We grabbed a reference, and there's one in the arglist, so account for them.
  223. sol_obj_free(obj);
  224. return res;
  225. }
  226. sol_object_t *sol_f_debug_setref(sol_state_t *state, sol_object_t *args) {
  227. sol_object_t *obj = sol_list_get_index(state, args, 0), *cnt = sol_list_get_index(state, args, 1);
  228. obj->refcnt = sol_cast_int(state, cnt)->ival + 2; // NB: As above.
  229. sol_obj_free(cnt);
  230. sol_obj_free(obj);
  231. return sol_incref(state->None);
  232. }
  233. sol_object_t *sol_f_debug_closure(sol_state_t *state, sol_object_t *args) {
  234. sol_object_t *func = sol_list_get_index(state, args, 0);
  235. sol_object_t *res = sol_incref(func->closure);
  236. sol_obj_free(func);
  237. return res;
  238. }
  239. sol_object_t *sol_f_debug_globals(sol_state_t *state, sol_object_t *args) {
  240. return sol_list_get_index(state, state->scopes, sol_list_len(state, state->scopes)-1);
  241. }
  242. sol_object_t *sol_f_debug_locals(sol_state_t *state, sol_object_t *args) {
  243. return sol_list_get_index(state, state->scopes, 0);
  244. }
  245. sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
  246. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  247. sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
  248. char temp[2] = {0, 0};
  249. if(sol_is_none(state, index)) {
  250. sol_obj_free(index);
  251. index = sol_new_int(state, 0);
  252. sol_map_set_name(state, local, "idx", index);
  253. }
  254. if(index->ival >= strlen(obj->str)) {
  255. sol_obj_free(index);
  256. sol_obj_free(obj);
  257. sol_obj_free(local);
  258. return sol_incref(state->StopIteration);
  259. }
  260. temp[0] = obj->str[index->ival];
  261. res = sol_new_string(state, temp);
  262. index->ival++;
  263. sol_obj_free(index);
  264. sol_obj_free(local);
  265. sol_obj_free(obj);
  266. return res;
  267. }
  268. sol_object_t *sol_f_iter_list(sol_state_t *state, sol_object_t *args) {
  269. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  270. sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
  271. if(sol_is_none(state, index)) {
  272. sol_obj_free(index);
  273. index = sol_new_int(state, 0);
  274. sol_map_set_name(state, local, "idx", index);
  275. }
  276. if(index->ival >= sol_list_len(state, obj)) {
  277. sol_obj_free(index);
  278. sol_obj_free(obj);
  279. sol_obj_free(local);
  280. return sol_incref(state->StopIteration);
  281. }
  282. res = sol_list_get_index(state, obj, index->ival);
  283. index->ival++;
  284. sol_obj_free(index);
  285. sol_obj_free(local);
  286. sol_obj_free(obj);
  287. return res;
  288. }
  289. sol_object_t *sol_f_iter_map(sol_state_t *state, sol_object_t *args) {
  290. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  291. sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
  292. if(sol_is_none(state, index)) {
  293. sol_obj_free(index);
  294. index = obj;
  295. sol_map_set_name(state, local, "idx", index);
  296. }
  297. if(!index || index == state->StopIteration) {
  298. sol_obj_free(index);
  299. sol_obj_free(obj);
  300. sol_obj_free(local);
  301. return sol_incref(state->StopIteration);
  302. }
  303. while(index && !index->mkey) index = index->mnext;
  304. res = sol_incref(index->mkey);
  305. index = index->mnext;
  306. if(!index) index = state->StopIteration;
  307. sol_map_set_name(state, local, "idx", index);
  308. sol_obj_free(index);
  309. sol_obj_free(local);
  310. sol_obj_free(obj);
  311. return res;
  312. }
  313. sol_object_t *sol_f_int_add(sol_state_t *state, sol_object_t *args) {
  314. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  315. sol_object_t *res = sol_new_int(state, a->ival + b->ival);
  316. sol_obj_free(a);
  317. sol_obj_free(b);
  318. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  319. return res;
  320. }
  321. sol_object_t *sol_f_int_sub(sol_state_t *state, sol_object_t *args) {
  322. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  323. sol_object_t *res = sol_new_int(state, a->ival - b->ival);
  324. sol_obj_free(a);
  325. sol_obj_free(b);
  326. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  327. return res;
  328. }
  329. sol_object_t *sol_f_int_mul(sol_state_t *state, sol_object_t *args) {
  330. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  331. sol_object_t *res = sol_new_int(state, a->ival * b->ival);
  332. sol_obj_free(a);
  333. sol_obj_free(b);
  334. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  335. return res;
  336. }
  337. sol_object_t *sol_f_int_div(sol_state_t *state, sol_object_t *args) {
  338. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  339. sol_object_t *res = sol_new_int(state, a->ival / b->ival);
  340. sol_obj_free(a);
  341. sol_obj_free(b);
  342. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  343. return res;
  344. }
  345. sol_object_t *sol_f_int_pow(sol_state_t *state, sol_object_t *args) {
  346. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  347. sol_object_t *res = sol_new_int(state, (long) pow((double) a->ival, b->ival));
  348. sol_obj_free(a);
  349. sol_obj_free(b);
  350. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  351. return res;
  352. }
  353. sol_object_t *sol_f_int_band(sol_state_t *state, sol_object_t *args) {
  354. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  355. sol_object_t *res = sol_new_int(state, a->ival & b->ival);
  356. sol_obj_free(a);
  357. sol_obj_free(b);
  358. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  359. return res;
  360. }
  361. sol_object_t *sol_f_int_bor(sol_state_t *state, sol_object_t *args) {
  362. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  363. sol_object_t *res = sol_new_int(state, a->ival | b->ival);
  364. sol_obj_free(a);
  365. sol_obj_free(b);
  366. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  367. return res;
  368. }
  369. sol_object_t *sol_f_int_bxor(sol_state_t *state, sol_object_t *args) {
  370. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  371. sol_object_t *res = sol_new_int(state, a->ival ^ b->ival);
  372. sol_obj_free(a);
  373. sol_obj_free(b);
  374. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  375. return res;
  376. }
  377. sol_object_t *sol_f_int_blsh(sol_state_t *state, sol_object_t *args) {
  378. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  379. sol_object_t *res = sol_new_int(state, a->ival << b->ival);
  380. sol_obj_free(a);
  381. sol_obj_free(b);
  382. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  383. return res;
  384. }
  385. sol_object_t *sol_f_int_brsh(sol_state_t *state, sol_object_t *args) {
  386. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  387. sol_object_t *res = sol_new_int(state, a->ival >> b->ival);
  388. sol_obj_free(a);
  389. sol_obj_free(b);
  390. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  391. return res;
  392. }
  393. sol_object_t *sol_f_int_bnot(sol_state_t *state, sol_object_t *args) {
  394. sol_object_t *a = sol_list_get_index(state, args, 0);
  395. sol_object_t *res = sol_new_int(state, ~a->ival);
  396. sol_obj_free(a);
  397. return res;
  398. }
  399. sol_object_t *sol_f_int_cmp(sol_state_t *state, sol_object_t *args) {
  400. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  401. sol_object_t *res = sol_new_int(state, a->ival==b->ival? 0 : (a->ival<b->ival? -1 : 1));
  402. sol_obj_free(a);
  403. sol_obj_free(b);
  404. return res;
  405. }
  406. sol_object_t *sol_f_int_toint(sol_state_t *state, sol_object_t *args) {
  407. return sol_list_get_index(state, args, 0);
  408. }
  409. sol_object_t *sol_f_int_tofloat(sol_state_t *state, sol_object_t *args) {
  410. sol_object_t *a = sol_list_get_index(state, args, 0);
  411. sol_object_t *res = sol_new_float(state, (double) a->ival);
  412. sol_obj_free(a);
  413. return res;
  414. }
  415. sol_object_t *sol_f_int_tostring(sol_state_t *state, sol_object_t *args) {
  416. sol_object_t *a = sol_list_get_index(state, args, 0);
  417. char *s = _itoa(a->ival);
  418. sol_object_t *res = sol_new_string(state, s);
  419. sol_obj_free(a);
  420. free(s);
  421. return res;
  422. }
  423. sol_object_t *sol_f_float_add(sol_state_t *state, sol_object_t *args) {
  424. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  425. sol_object_t *res = sol_new_float(state, a->fval + b->fval);
  426. sol_obj_free(a);
  427. sol_obj_free(b);
  428. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  429. return res;
  430. }
  431. sol_object_t *sol_f_float_sub(sol_state_t *state, sol_object_t *args) {
  432. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  433. sol_object_t *res = sol_new_float(state, a->fval - b->fval);
  434. sol_obj_free(a);
  435. sol_obj_free(b);
  436. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  437. return res;
  438. }
  439. sol_object_t *sol_f_float_mul(sol_state_t *state, sol_object_t *args) {
  440. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  441. sol_object_t *res = sol_new_float(state, a->fval * b->fval);
  442. sol_obj_free(a);
  443. sol_obj_free(b);
  444. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  445. return res;
  446. }
  447. sol_object_t *sol_f_float_div(sol_state_t *state, sol_object_t *args) {
  448. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  449. sol_object_t *res = sol_new_float(state, a->fval / b->fval);
  450. sol_obj_free(a);
  451. sol_obj_free(b);
  452. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  453. return res;
  454. }
  455. sol_object_t *sol_f_float_pow(sol_state_t *state, sol_object_t *args) {
  456. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  457. sol_object_t *res = sol_new_float(state, pow(a->fval, b->fval));
  458. sol_obj_free(a);
  459. sol_obj_free(b);
  460. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  461. return res;
  462. }
  463. sol_object_t *sol_f_float_cmp(sol_state_t *state, sol_object_t *args) {
  464. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_float(state, sol_list_get_index(state, args, 1));
  465. sol_object_t *res = sol_new_int(state, a->fval==b->fval? 0 : (a->fval<b->fval? -1 : 1));
  466. sol_obj_free(a);
  467. sol_obj_free(b);
  468. return res;
  469. }
  470. sol_object_t *sol_f_float_toint(sol_state_t *state, sol_object_t *args) {
  471. sol_object_t *a = sol_list_get_index(state, args, 0);
  472. sol_object_t *res = sol_new_int(state, (int) a->fval);
  473. sol_obj_free(a);
  474. return res;
  475. }
  476. sol_object_t *sol_f_float_tofloat(sol_state_t *state, sol_object_t *args) {
  477. return sol_list_get_index(state, args, 0);
  478. }
  479. sol_object_t *sol_f_float_tostring(sol_state_t *state, sol_object_t *args) {
  480. sol_object_t *a = sol_list_get_index(state, args, 0);
  481. char *s = _ftoa(a->fval);
  482. sol_object_t *res = sol_new_string(state, s);
  483. sol_obj_free(a);
  484. free(s);
  485. return res;
  486. }
  487. sol_object_t *sol_f_str_add(sol_state_t *state, sol_object_t *args) {
  488. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_string(state, sol_list_get_index(state, args, 1));
  489. int n = strlen(a->str) + strlen(b->str) + 1;
  490. char *s = malloc(n);
  491. sol_object_t *res = sol_new_string(state, strncat(strncpy(s, a->str, n), b->str, n));
  492. sol_obj_free(a);
  493. sol_obj_free(b);
  494. free(s);
  495. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  496. return res;
  497. }
  498. sol_object_t *sol_f_str_mul(sol_state_t *state, sol_object_t *args) {
  499. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1));
  500. int n = strlen(a->str) * b->ival + 1;
  501. char *s = malloc(n);
  502. int i;
  503. s[0]='\0';
  504. for(i = 0; i < b->ival; i++) strncat(s, a->str, n);
  505. sol_object_t *res = sol_new_string(state, s);
  506. sol_obj_free(a);
  507. sol_obj_free(b);
  508. free(s);
  509. if(sol_has_error(state)) {sol_obj_free(res); return sol_incref(state->None);}
  510. return res;
  511. }
  512. sol_object_t *sol_f_str_cmp(sol_state_t *state, sol_object_t *args) {
  513. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_string(state, sol_list_get_index(state, args, 1));
  514. sol_object_t *res = sol_new_int(state, strcmp(a->str, b->str));
  515. sol_obj_free(a);
  516. sol_obj_free(b);
  517. return res;
  518. }
  519. sol_object_t *sol_f_str_len(sol_state_t *state, sol_object_t *args) {
  520. sol_object_t *a = sol_list_get_index(state, args, 0);
  521. sol_object_t *res = sol_new_int(state, strlen(a->str));
  522. sol_obj_free(a);
  523. return res;
  524. }
  525. sol_object_t *sol_f_str_iter(sol_state_t *state, sol_object_t *args) {
  526. return sol_new_cfunc(state, sol_f_iter_str);
  527. }
  528. sol_object_t *sol_f_str_toint(sol_state_t *state, sol_object_t *args) {
  529. sol_object_t *a = sol_list_get_index(state, args, 0);
  530. sol_object_t *res = sol_new_int(state, atoi(a->str));
  531. sol_obj_free(a);
  532. return res;
  533. }
  534. sol_object_t *sol_f_str_tofloat(sol_state_t *state, sol_object_t *args) {
  535. sol_object_t *a = sol_list_get_index(state, args, 0);
  536. sol_object_t *res = sol_new_float(state, atof(a->str));
  537. sol_obj_free(a);
  538. return res;
  539. }
  540. sol_object_t *sol_f_str_tostring(sol_state_t *state, sol_object_t *args) {
  541. return sol_list_get_index(state, args, 0);
  542. }
  543. sol_object_t *sol_f_list_add(sol_state_t *state, sol_object_t *args) {
  544. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ls;
  545. if(!sol_is_list(b)) {
  546. sol_obj_free(a);
  547. sol_obj_free(b);
  548. return sol_set_error_string(state, "Adding list to non-list");
  549. }
  550. ls = sol_list_copy(state, a);
  551. sol_list_append(state, ls, b);
  552. sol_obj_free(a);
  553. sol_obj_free(b);
  554. return ls;
  555. }
  556. sol_object_t *sol_f_list_mul(sol_state_t *state, sol_object_t *args) {
  557. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args, 1)), *ls;
  558. int i;
  559. if(sol_has_error(state)) {
  560. sol_obj_free(a);
  561. sol_obj_free(b);
  562. return sol_incref(state->None);
  563. }
  564. ls = sol_new_list(state);
  565. for(i = 0; i < b->ival; i++) {
  566. sol_list_append(state, ls, a);
  567. if(sol_has_error(state)) {
  568. sol_obj_free(a);
  569. sol_obj_free(b);
  570. return sol_incref(state->None);
  571. }
  572. }
  573. return ls;
  574. }
  575. sol_object_t *sol_f_list_index(sol_state_t *state, sol_object_t *args) {
  576. sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ival;
  577. sol_object_t *res;
  578. if(sol_is_string(b)) {
  579. res = sol_map_get(state, state->ListFuncs, b);
  580. } else {
  581. ival = sol_cast_int(state, b);
  582. res = sol_list_get_index(state, ls, ival->ival);
  583. if(ival!=b) sol_obj_free(ival);
  584. }
  585. sol_obj_free(ls);
  586. sol_obj_free(b);
  587. return res;
  588. }
  589. sol_object_t *sol_f_list_setindex(sol_state_t *state, sol_object_t *args) {
  590. sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_cast_int(state, sol_list_get_index(state, args ,1));
  591. sol_object_t *val = sol_list_get_index(state, args, 2);
  592. sol_list_set_index(state, ls, b->ival, val);
  593. sol_obj_free(ls);
  594. sol_obj_free(b);
  595. sol_obj_free(val);
  596. return sol_incref(state->None);
  597. }
  598. sol_object_t *sol_f_list_len(sol_state_t *state, sol_object_t *args) {
  599. sol_object_t *ls = sol_list_get_index(state, args, 0);
  600. sol_object_t *res = sol_new_int(state, sol_list_len(state, ls));
  601. sol_obj_free(ls);
  602. return res;
  603. }
  604. sol_object_t *sol_f_list_iter(sol_state_t *state, sol_object_t *args) {
  605. return sol_new_cfunc(state, sol_f_iter_list);
  606. }
  607. sol_object_t *sol_f_list_tostring(sol_state_t *state, sol_object_t *args) {
  608. return sol_new_string(state, "<List>");
  609. }
  610. sol_object_t *sol_f_list_copy(sol_state_t *state, sol_object_t *args) {
  611. sol_object_t *list = sol_list_get_index(state, args, 0);
  612. sol_object_t *res = sol_list_copy(state, list);
  613. sol_obj_free(list);
  614. return res;
  615. }
  616. sol_object_t *sol_f_list_insert(sol_state_t *state, sol_object_t *args) {
  617. sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_cast_int(state, sol_list_get_index(state, args, 1)), *obj = sol_list_get_index(state, args, 2);
  618. sol_list_insert(state, list, idx->ival, obj);
  619. sol_obj_free(list);
  620. return sol_incref(state->None);
  621. }
  622. sol_object_t *sol_f_list_remove(sol_state_t *state, sol_object_t *args) {
  623. sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_cast_int(state, sol_list_get_index(state, args, 1));
  624. sol_list_remove(state, list, idx->ival);
  625. sol_obj_free(list);
  626. return sol_incref(state->None);
  627. }
  628. sol_object_t *sol_f_list_truncate(sol_state_t *state, sol_object_t *args) {
  629. sol_object_t *list = sol_list_get_index(state, args, 0), *idx = sol_list_get_index(state, args, 1);
  630. sol_object_t *res = sol_list_truncate(state, list, idx->ival);
  631. sol_obj_free(list);
  632. return res;
  633. }
  634. sol_object_t *sol_f_list_map(sol_state_t *state, sol_object_t *args) {
  635. sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
  636. sol_object_t *fargs = sol_new_list(state), *item;
  637. int idx=0, len = sol_list_len(state, list);
  638. sol_list_insert(state, fargs, 0, func);
  639. while(idx<len) {
  640. item = sol_list_get_index(state, list, idx);
  641. sol_list_insert(state, fargs, 1, item);
  642. sol_obj_free(item);
  643. item = func->ops->call(state, fargs);
  644. if(sol_has_error(state)) return list;
  645. sol_list_remove(state, fargs, 1);
  646. sol_list_set_index(state, list, idx, item);
  647. sol_obj_free(item);
  648. idx++;
  649. }
  650. sol_obj_free(fargs);
  651. sol_obj_free(func);
  652. return list;
  653. }
  654. sol_object_t *sol_f_list_filter(sol_state_t *state, sol_object_t *args) {
  655. sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
  656. sol_object_t *fargs = sol_new_list(state), *item, *ival;
  657. int idx=0, len = sol_list_len(state, list);
  658. sol_list_insert(state, fargs, 0, func);
  659. while(idx<len) {
  660. item = sol_list_get_index(state, list, idx);
  661. sol_list_insert(state, fargs, 1, item);
  662. sol_obj_free(item);
  663. item = func->ops->call(state, fargs);
  664. if(sol_has_error(state)) return list;
  665. ival = sol_cast_int(state, item);
  666. if(ival->ival) {
  667. idx++;
  668. } else {
  669. sol_list_remove(state, list, idx);
  670. len--;
  671. }
  672. if(ival!=item) sol_obj_free(item);
  673. sol_obj_free(ival);
  674. }
  675. sol_obj_free(fargs);
  676. sol_obj_free(func);
  677. return list;
  678. }
  679. sol_object_t *sol_f_map_add(sol_state_t *state, sol_object_t *args) {
  680. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *map;
  681. if(!sol_is_map(b)) {
  682. sol_obj_free(a);
  683. sol_obj_free(b);
  684. return sol_set_error_string(state, "Adding map to non-map");
  685. }
  686. map = sol_map_copy(state, a);
  687. sol_map_merge(state, map, b);
  688. sol_obj_free(a);
  689. sol_obj_free(b);
  690. return map;
  691. }
  692. sol_object_t *sol_f_map_index(sol_state_t *state, sol_object_t *args) {
  693. sol_object_t *map = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  694. sol_object_t *indexf = sol_map_get_name(state, map, "__index");
  695. sol_object_t *res = NULL, *newls;
  696. if(!sol_is_none(state, indexf)) {
  697. if(indexf->ops->call && (sol_is_func(indexf) || sol_is_cfunc(indexf)) && indexf->ops->call != sol_f_not_impl) {
  698. newls = sol_new_list(state);
  699. sol_list_insert(state, newls, 0, indexf);
  700. sol_list_append(state, newls, args);
  701. res = indexf->ops->call(state, newls);
  702. sol_obj_free(newls);
  703. } else if(indexf->ops->index && indexf->ops->index != sol_f_not_impl) {
  704. newls = sol_new_list(state);
  705. sol_list_insert(state, newls, 0, indexf);
  706. sol_list_insert(state, newls, 1, b);
  707. res = indexf->ops->index(state, newls);
  708. sol_obj_free(newls);
  709. }
  710. }
  711. if(!res) res = sol_map_get(state, map, b);
  712. sol_obj_free(indexf);
  713. sol_obj_free(map);
  714. sol_obj_free(b);
  715. return res;
  716. }
  717. sol_object_t *sol_f_map_setindex(sol_state_t *state, sol_object_t *args) {
  718. sol_object_t *map = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  719. sol_object_t *val = sol_list_get_index(state, args, 2);
  720. sol_object_t *setindexf = sol_map_get_name(state, map, "__setindex"), *newls;
  721. if(!sol_is_none(state, setindexf)) {
  722. if(setindexf->ops->call && (sol_is_func(setindexf) || sol_is_cfunc(setindexf)) && setindexf->ops->call != sol_f_not_impl) {
  723. newls = sol_new_list(state);
  724. sol_list_insert(state, newls, 0, setindexf);
  725. sol_list_append(state, newls, args);
  726. sol_obj_free(setindexf->ops->call(state, newls));
  727. sol_obj_free(newls);
  728. return sol_incref(state->None);
  729. } else if(setindexf->ops->setindex && setindexf->ops->setindex != sol_f_not_impl) {
  730. newls = sol_new_list(state);
  731. sol_list_insert(state, newls, 0, setindexf);
  732. sol_list_insert(state, newls, 1, b);
  733. sol_list_insert(state, newls, 2, val);
  734. sol_obj_free(setindexf->ops->index(state, newls));
  735. sol_obj_free(newls);
  736. return sol_incref(state->None);
  737. }
  738. }
  739. sol_obj_free(setindexf);
  740. sol_map_set(state, map, b, val);
  741. sol_obj_free(map);
  742. sol_obj_free(b);
  743. sol_obj_free(val);
  744. return sol_incref(state->None);
  745. }
  746. sol_object_t *sol_f_map_call(sol_state_t *state, sol_object_t *args) {
  747. sol_object_t *map = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
  748. sol_object_t *callf = sol_map_get_name(state, map, "__call"), *res = NULL;
  749. if(!sol_is_none(state, callf)) {
  750. if(callf->ops->call) {
  751. sol_list_insert(state, fargs, 0, callf);
  752. sol_list_insert(state, fargs, 1, map);
  753. res = callf->ops->call(state, fargs);
  754. }
  755. }
  756. sol_obj_free(map);
  757. sol_obj_free(fargs);
  758. sol_obj_free(callf);
  759. if(res) return res;
  760. return sol_set_error_string(state, "Call map without call method");
  761. }
  762. sol_object_t *sol_f_map_len(sol_state_t *state, sol_object_t *args) {
  763. sol_object_t *map = sol_list_get_index(state, args, 0);
  764. sol_object_t *res = sol_new_int(state, sol_map_len(state, map));
  765. sol_obj_free(map);
  766. return res;
  767. }
  768. sol_object_t *sol_f_map_iter(sol_state_t *state, sol_object_t *args) {
  769. return sol_new_cfunc(state, sol_f_iter_map);
  770. }
  771. sol_object_t *sol_f_map_tostring(sol_state_t *state, sol_object_t *args) {
  772. return sol_new_string(state, "<Map>");
  773. }
  774. sol_object_t *sol_f_func_index(sol_state_t *state, sol_object_t *args) {
  775. sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *res;
  776. res = sol_map_get(state, func->closure, key);
  777. sol_obj_free(func);
  778. sol_obj_free(key);
  779. return res;
  780. }
  781. sol_object_t *sol_f_func_setindex(sol_state_t *state, sol_object_t *args) {
  782. sol_object_t *func = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *val = sol_list_get_index(state, args, 2);
  783. sol_map_set(state, func->closure, key, val);
  784. sol_obj_free(func);
  785. sol_obj_free(key);
  786. sol_obj_free(val);
  787. return sol_incref(state->None);
  788. }
  789. sol_object_t *sol_f_func_tostring(sol_state_t *state, sol_object_t *args) {
  790. return sol_new_string(state, "<Function>");
  791. }
  792. sol_object_t *sol_f_cfunc_call(sol_state_t *state, sol_object_t *args) {
  793. sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
  794. sol_object_t *res = func->cfunc(state, fargs);
  795. sol_obj_free(func);
  796. sol_obj_free(fargs);
  797. return res;
  798. }
  799. sol_object_t *sol_f_cfunc_tostring(sol_state_t *state, sol_object_t *args) {
  800. return sol_new_string(state, "<CFunction>");
  801. }