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.

2745 lines
81 KiB

  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <stdint.h>
  6. #include <dlfcn.h>
  7. #include <readline/readline.h>
  8. #include <readline/history.h>
  9. #include "ast.h"
  10. #include "dsl/dsl.h"
  11. // XXX hardcoded buffer sizes
  12. #define STDIO_CHUNK_SIZE 4096
  13. static char *_itoa(int i) {
  14. int n = 33;
  15. char *s = malloc(n);
  16. snprintf(s, n, "%d", i);
  17. return s;
  18. }
  19. static char *_ftoa(double f) {
  20. int n = 65;
  21. char *s = malloc(n);
  22. snprintf(s, n, "%f", f);
  23. return s;
  24. }
  25. sol_object_t *sol_f_not_impl(sol_state_t *state, sol_object_t *args) {
  26. char buffer[64];
  27. snprintf(buffer, 64, "Undefined method (%s on %s)", state->calling_meth, state->calling_type);
  28. return sol_set_error_string(state, buffer);
  29. }
  30. sol_object_t *sol_f_default_cmp(sol_state_t *state, sol_object_t *args) {
  31. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  32. sol_object_t *res = sol_new_int(state, a != b);
  33. sol_obj_free(a);
  34. sol_obj_free(b);
  35. return res;
  36. }
  37. sol_object_t *sol_f_default_tostring(sol_state_t *state, sol_object_t *args) {
  38. sol_object_t *obj = sol_list_get_index(state, args, 0);
  39. char s[64];
  40. snprintf(s, 64, "<%s object at %p>", obj->ops->tname, obj);
  41. sol_obj_free(obj);
  42. return sol_new_string(state, s);
  43. }
  44. sol_object_t *sol_f_default_repr(sol_state_t *state, sol_object_t *args) {
  45. sol_object_t *obj = sol_list_get_index(state, args, 0), *res = CALL_METHOD(state, obj, tostring, args);
  46. sol_obj_free(obj);
  47. return res;
  48. }
  49. sol_object_t *sol_f_tbang(sol_state_t *state, sol_object_t *args) {
  50. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  51. int refa = a->refcnt, refb = b->refcnt;
  52. sol_object_t c = *b;
  53. *b = *a;
  54. *a = c;
  55. b->refcnt = refa;
  56. a->refcnt = refb;
  57. sol_obj_free(a);
  58. sol_obj_free(b);
  59. return sol_incref(state->None);
  60. }
  61. sol_object_t *sol_f_no_op(sol_state_t *state, sol_object_t *args) {
  62. if(state) {
  63. return sol_incref(state->None);
  64. }
  65. return NULL;
  66. }
  67. sol_object_t *sol_f_toint(sol_state_t *state, sol_object_t *args) {
  68. sol_object_t *obj = sol_list_get_index(state, args, 0);
  69. sol_object_t *res = CALL_METHOD(state, obj, toint, args);
  70. sol_obj_free(obj);
  71. return res;
  72. }
  73. sol_object_t *sol_f_tofloat(sol_state_t *state, sol_object_t *args) {
  74. sol_object_t *obj = sol_list_get_index(state, args, 0);
  75. sol_object_t *res = CALL_METHOD(state, obj, tofloat, args);
  76. sol_obj_free(obj);
  77. return res;
  78. }
  79. sol_object_t *sol_f_tostring(sol_state_t *state, sol_object_t *args) {
  80. sol_object_t *obj = sol_list_get_index(state, args, 0);
  81. sol_object_t *res = CALL_METHOD(state, obj, tostring, args);
  82. sol_obj_free(obj);
  83. return res;
  84. }
  85. sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
  86. sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
  87. sol_object_t *ls = sol_new_list(state), *one = sol_new_int(state, 1);
  88. sol_object_t *res;
  89. sol_list_insert(state, fargs, 0, func);
  90. res = CALL_METHOD(state, func, call, fargs);
  91. sol_obj_free(func);
  92. sol_obj_free(fargs);
  93. if(sol_has_error(state)) {
  94. sol_object_t *err = sol_get_error(state);
  95. sol_clear_error(state);
  96. sol_object_t *zero = sol_new_int(state, 0);
  97. sol_obj_free(res);
  98. sol_obj_free(one);
  99. sol_list_insert(state, ls, 0, err);
  100. sol_obj_free(err);
  101. sol_list_insert(state, ls, 0, zero);
  102. sol_obj_free(zero);
  103. sol_list_insert(state, ls, 2, state->traceback);
  104. sol_obj_free(state->traceback);
  105. state->traceback = NULL;
  106. return ls;
  107. }
  108. sol_list_insert(state, ls, 0, res);
  109. sol_obj_free(res);
  110. sol_list_insert(state, ls, 0, one);
  111. sol_obj_free(one);
  112. return ls;
  113. }
  114. sol_object_t *sol_f_apply(sol_state_t *state, sol_object_t *args) {
  115. sol_object_t *func = sol_list_get_index(state, args, 0), *arglist = sol_list_get_index(state, args, 1), *rest = sol_list_sublist(state, args, 2);
  116. sol_list_append(state, rest, arglist);
  117. sol_obj_free(arglist);
  118. sol_list_insert(state, rest, 0, func);
  119. sol_object_t *res = CALL_METHOD(state, func, call, rest);
  120. sol_obj_free(rest);
  121. sol_obj_free(func);
  122. return res;
  123. }
  124. sol_object_t *sol_f_error(sol_state_t *state, sol_object_t *args) {
  125. sol_object_t *arg = sol_list_get_index(state, args, 0), *res;
  126. res = sol_set_error(state, arg);
  127. sol_obj_free(arg);
  128. return res;
  129. }
  130. sol_object_t *sol_f_type(sol_state_t *state, sol_object_t *args) {
  131. sol_object_t *obj = sol_list_get_index(state, args, 0);
  132. sol_object_t *res = sol_new_string(state, obj->ops->tname);
  133. sol_obj_free(obj);
  134. return res;
  135. }
  136. static dsl_seq *seen = NULL;
  137. int test_seen(sol_object_t *obj) {
  138. dsl_seq_iter *iter;
  139. if(seen) {
  140. iter = dsl_new_seq_iter(seen);
  141. while(!dsl_seq_iter_is_invalid(iter)) {
  142. if(dsl_seq_iter_at(iter) == obj) {
  143. return 1;
  144. }
  145. dsl_seq_iter_next(iter);
  146. }
  147. dsl_free_seq_iter(iter);
  148. dsl_seq_insert(seen, dsl_seq_len(seen), obj);
  149. }
  150. return 0;
  151. }
  152. void ob_print(sol_object_t *obj) {
  153. sol_object_t *cur;
  154. dsl_seq_iter *iter;
  155. int i;
  156. if(test_seen(obj)) {
  157. return;
  158. }
  159. switch(obj->type) {
  160. case SOL_SINGLET:
  161. printf("%s", obj->str);
  162. break;
  163. case SOL_INTEGER:
  164. printf("%ld", obj->ival);
  165. break;
  166. case SOL_FLOAT:
  167. printf("%f", obj->fval);
  168. break;
  169. case SOL_STRING:
  170. printf("\"%s\"", obj->str);
  171. break;
  172. case SOL_LIST:
  173. printf("[");
  174. iter = dsl_new_seq_iter(obj->seq);
  175. while(!dsl_seq_iter_is_invalid(iter)) {
  176. ob_print(dsl_seq_iter_at(iter));
  177. printf(", ");
  178. dsl_seq_iter_next(iter);
  179. }
  180. dsl_free_seq_iter(iter);
  181. printf("]");
  182. break;
  183. case SOL_MCELL:
  184. printf("<<");
  185. ob_print(obj->key);
  186. printf("=");
  187. ob_print(obj->val);
  188. printf(">>");
  189. case SOL_MAP:
  190. printf("{");
  191. iter = dsl_new_seq_iter(obj->seq);
  192. while(!dsl_seq_iter_is_invalid(iter)) {
  193. printf("[");
  194. ob_print(AS_OBJ(dsl_seq_iter_at(iter))->key);
  195. printf("] = ");
  196. ob_print(AS_OBJ(dsl_seq_iter_at(iter))->val);
  197. printf(", ");
  198. dsl_seq_iter_next(iter);
  199. }
  200. dsl_free_seq_iter(iter);
  201. printf("}");
  202. break;
  203. case SOL_FUNCTION:
  204. if(obj->fname) {
  205. printf("<Function %s>", obj->fname);
  206. } else {
  207. printf("<Function>");
  208. }
  209. break;
  210. case SOL_CFUNCTION:
  211. printf("<CFunction>");
  212. break;
  213. case SOL_STMT:
  214. st_print(NULL, obj->node); //TODO: FIXME
  215. break;
  216. case SOL_EXPR:
  217. ex_print(NULL, obj->node); //TODO: FIXME
  218. break;
  219. case SOL_BUFFER:
  220. if(obj->sz == -1) {
  221. printf("<Buffer @%p>", obj->buffer);
  222. } else {
  223. printf("<Buffer @%p size %ld>", obj->buffer, obj->sz);
  224. }
  225. break;
  226. case SOL_CDATA:
  227. printf("<CData>");
  228. break;
  229. /*default:
  230. cur = sol_cast_string(state, obj);
  231. printf("%s", cur->str);
  232. sol_obj_free(cur);*/
  233. }
  234. }
  235. sol_object_t *sol_f_prepr(sol_state_t *state, sol_object_t *args) {
  236. int i, sz = sol_list_len(state, args);
  237. sol_object_t *obj, *str;
  238. seen = dsl_seq_new_array(NULL, NULL);
  239. for(i = 0; i < sz; i++) {
  240. obj = sol_list_get_index(state, args, i);
  241. str = sol_cast_repr(state, obj);
  242. sol_printf(state, "%s", str->str);
  243. sol_printf(state, " ");
  244. sol_obj_free(obj);
  245. sol_obj_free(str);
  246. }
  247. sol_printf(state, "\n");
  248. printf("\n");
  249. dsl_free_seq(seen);
  250. seen = NULL;
  251. return sol_incref(state->None);
  252. }
  253. sol_object_t *sol_f_print(sol_state_t *state, sol_object_t *args) {
  254. int i, sz = sol_list_len(state, args);
  255. sol_object_t *obj, *str;
  256. seen = dsl_seq_new_array(NULL, NULL);
  257. for(i = 0; i < sz; i++) {
  258. obj = sol_list_get_index(state, args, i);
  259. str = sol_cast_string(state, obj);
  260. sol_printf(state, "%s", str->str);
  261. sol_printf(state, " ");
  262. sol_obj_free(obj);
  263. sol_obj_free(str);
  264. }
  265. sol_printf(state, "\n");
  266. dsl_free_seq(seen);
  267. seen = NULL;
  268. return sol_incref(state->None);
  269. }
  270. sol_object_t *sol_f_rawget(sol_state_t *state, sol_object_t *args) {
  271. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *res;
  272. if(!sol_is_map(obj)) {
  273. return sol_set_error_string(state, "Rawset of non-map");
  274. }
  275. key = sol_list_get_index(state, args, 1);
  276. res = sol_map_get(state, obj, key);
  277. sol_obj_free(key);
  278. sol_obj_free(obj);
  279. return res;
  280. }
  281. sol_object_t *sol_f_rawset(sol_state_t *state, sol_object_t *args) {
  282. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *val;
  283. if(!sol_is_map(obj)) {
  284. return sol_set_error_string(state, "Rawset of non-map");
  285. }
  286. key = sol_list_get_index(state, args, 1);
  287. val = sol_list_get_index(state, args, 2);
  288. sol_map_set(state, obj, key, val);
  289. sol_obj_free(val);
  290. sol_obj_free(key);
  291. sol_obj_free(obj);
  292. return sol_incref(state->None);
  293. }
  294. sol_object_t *sol_f_range(sol_state_t *state, sol_object_t *args) {
  295. sol_object_t *res = sol_new_list(state), *bound = sol_cast_int(state, sol_list_get_index(state, args, 0));
  296. int i;
  297. for(i = 0; i < bound->ival; i++) {
  298. sol_list_insert(state, res, sol_list_len(state, res), sol_new_int(state, i));
  299. }
  300. sol_obj_free(bound);
  301. return res;
  302. }
  303. sol_object_t *sol_f_exec(sol_state_t *state, sol_object_t *args) {
  304. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  305. stmt_node *program;
  306. program = sol_compile(prgstr->str);
  307. if(!program) {
  308. return sol_set_error_string(state, "Compilation failure");
  309. }
  310. // XXX should st_free(program);
  311. sol_exec(state, program);
  312. return sol_incref(state->None);
  313. }
  314. sol_object_t *sol_f_eval(sol_state_t *state, sol_object_t *args) {
  315. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  316. stmt_node *program;
  317. program = sol_compile(prgstr->str);
  318. if(!program) {
  319. return sol_set_error_string(state, "Compilation failure");
  320. }
  321. if(program->type != ST_LIST || program->stmtlist->stmt->type != ST_EXPR) {
  322. return sol_set_error_string(state, "Not an expression");
  323. }
  324. // XXX should st_free(program);
  325. return sol_eval(state, program->stmtlist->stmt->expr);
  326. }
  327. sol_object_t *sol_f_execfile(sol_state_t *state, sol_object_t *args) {
  328. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  329. stmt_node *program;
  330. FILE *f = fopen(prgstr->str, "r");
  331. char *s;
  332. long sz;
  333. if(!f) {
  334. return sol_set_error_string(state, "File open failure");
  335. }
  336. fseek(f, 0, SEEK_END);
  337. sz = ftell(f);
  338. fseek(f, 0, SEEK_SET);
  339. s = malloc(sz + 1);
  340. if(!s) {
  341. fclose(f);
  342. return sol_set_error_string(state, "File memory allocation failure");
  343. }
  344. fread(s, 1, sz, f);
  345. s[sz] = 0;
  346. fclose(f);
  347. program = sol_compile(s);
  348. free(s);
  349. if(!program) {
  350. return sol_set_error_string(state, "Compilation failure");
  351. }
  352. // XXX should st_free(program);
  353. sol_exec(state, program);
  354. return sol_incref(state->None);
  355. }
  356. sol_object_t *sol_f_parse(sol_state_t *state, sol_object_t *args) {
  357. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  358. stmt_node *program = sol_compile(prgstr->str);
  359. sol_obj_free(prg);
  360. sol_obj_free(prgstr);
  361. if(!program) {
  362. return sol_set_error_string(state, "Compilation failure");
  363. }
  364. return sol_new_stmtnode(state, program);
  365. }
  366. sol_object_t *sol_f_ord(sol_state_t *state, sol_object_t *args) {
  367. sol_object_t *arg = sol_list_get_index(state, args, 0), *str = sol_cast_string(state, arg);
  368. sol_object_t *arg2, *iarg, *res;
  369. long idx = 0;
  370. size_t len = strlen(str->str);
  371. sol_obj_free(arg);
  372. if(sol_list_len(state, args) > 1) {
  373. arg2 = sol_list_get_index(state, args, 1);
  374. iarg = sol_cast_int(state, arg2);
  375. sol_obj_free(arg2);
  376. idx = iarg->ival;
  377. sol_obj_free(iarg);
  378. }
  379. if(idx < 0) {
  380. idx += len;
  381. }
  382. if(idx < 0 || idx >= len) {
  383. sol_obj_free(str);
  384. return sol_set_error_string(state, "Compute ord of out-of-bounds index");
  385. }
  386. res = sol_new_int(state, str->str[idx]);
  387. sol_obj_free(str);
  388. return res;
  389. }
  390. sol_object_t *sol_f_chr(sol_state_t *state, sol_object_t *args) {
  391. sol_object_t *arg = sol_list_get_index(state, args, 0), *iarg = sol_cast_int(state, arg);
  392. char cbuf[2] = {iarg->ival, 0};
  393. sol_object_t *res = sol_new_string(state, cbuf);
  394. sol_obj_free(arg);
  395. sol_obj_free(iarg);
  396. return res;
  397. }
  398. sol_object_t *sol_f_debug_getref(sol_state_t *state, sol_object_t *args) {
  399. sol_object_t *obj = sol_list_get_index(state, args, 0);
  400. 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.
  401. sol_obj_free(obj);
  402. return res;
  403. }
  404. sol_object_t *sol_f_debug_setref(sol_state_t *state, sol_object_t *args) {
  405. sol_object_t *obj = sol_list_get_index(state, args, 0), *cnt = sol_list_get_index(state, args, 1);
  406. obj->refcnt = sol_cast_int(state, cnt)->ival + 2; // NB: As above.
  407. sol_obj_free(cnt);
  408. sol_obj_free(obj);
  409. return sol_incref(state->None);
  410. }
  411. sol_object_t *sol_f_debug_closure(sol_state_t *state, sol_object_t *args) {
  412. sol_object_t *func = sol_list_get_index(state, args, 0);
  413. sol_object_t *res = sol_incref(func->closure);
  414. sol_obj_free(func);
  415. return res;
  416. }
  417. sol_object_t *sol_f_debug_globals(sol_state_t *state, sol_object_t *args) {
  418. return sol_list_get_index(state, state->scopes, sol_list_len(state, state->scopes) - 1);
  419. }
  420. sol_object_t *sol_f_debug_locals(sol_state_t *state, sol_object_t *args) {
  421. return sol_list_get_index(state, state->scopes, 0);
  422. }
  423. sol_object_t *sol_f_debug_scopes(sol_state_t *state, sol_object_t *args) {
  424. return sol_incref(state->scopes);
  425. }
  426. sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
  427. sol_object_t *obj, *objstr, *res;
  428. char *line;
  429. if(sol_list_len(state, args) > 0) {
  430. obj = sol_list_get_index(state, args, 0);
  431. objstr = sol_cast_string(state, obj);
  432. line = readline(objstr->str);
  433. sol_obj_free(obj);
  434. sol_obj_free(objstr);
  435. } else {
  436. line = readline("");
  437. }
  438. if(line) {
  439. res = sol_new_string(state, line);
  440. free(line);
  441. } else {
  442. res = sol_new_string(state, "");
  443. }
  444. return res;
  445. }
  446. sol_object_t *sol_f_readline_add_history(sol_state_t *state, sol_object_t *args) {
  447. sol_object_t *line = sol_list_get_index(state, args, 0), *linestr = sol_cast_string(state, line);
  448. add_history(linestr->str);
  449. sol_obj_free(linestr);
  450. sol_obj_free(line);
  451. return sol_incref(state->None);
  452. }
  453. void _sol_freef_seq_iter(void *iter, size_t sz) {
  454. dsl_free_seq_iter((dsl_seq_iter *) iter);
  455. }
  456. sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
  457. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  458. sol_object_t *index = sol_map_get_name(state, local, "idx"), *max = sol_map_get_name(state, local, "sz"), *res;
  459. char temp[2] = {0, 0};
  460. if(sol_is_none(state, index) || sol_is_none(state, max)) {
  461. sol_obj_free(index);
  462. index = sol_new_buffer(state, (void *) 0, sizeof(void *), OWN_NONE, NULL, NULL);
  463. sol_map_set_name(state, local, "idx", index);
  464. sol_obj_free(max);
  465. max = sol_new_int(state, strlen(obj->str));
  466. sol_map_set_name(state, local, "sz", max);
  467. }
  468. if(((size_t) index->buffer) >= max->ival) {
  469. sol_obj_free(index);
  470. sol_obj_free(obj);
  471. sol_obj_free(local);
  472. return sol_incref(state->None);
  473. }
  474. temp[0] = obj->str[((size_t) index->buffer)];
  475. res = sol_new_string(state, temp);
  476. index->buffer = (void *) ((size_t) index->buffer + 1);
  477. sol_obj_free(index);
  478. sol_obj_free(local);
  479. sol_obj_free(obj);
  480. return res;
  481. }
  482. sol_object_t *sol_f_iter_list(sol_state_t *state, sol_object_t *args) {
  483. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  484. sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
  485. if(sol_is_none(state, index)) {
  486. sol_obj_free(index);
  487. index = sol_new_buffer(state, dsl_new_seq_iter(obj->seq), sizeof(dsl_seq_iter), OWN_CALLF, _sol_freef_seq_iter, NULL);
  488. sol_map_set_name(state, local, "idx", index);
  489. sol_obj_free(index);
  490. }
  491. if(dsl_seq_iter_is_invalid(index->buffer)) {
  492. sol_obj_free(index);
  493. sol_obj_free(obj);
  494. sol_obj_free(local);
  495. return sol_incref(state->None);
  496. }
  497. res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer)));
  498. dsl_seq_iter_next(index->buffer);
  499. sol_obj_free(local);
  500. sol_obj_free(obj);
  501. return res;
  502. }
  503. sol_object_t *sol_f_iter_map(sol_state_t *state, sol_object_t *args) {
  504. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  505. sol_object_t *index = sol_map_get_name(state, local, "idx"), *res;
  506. if(sol_is_none(state, index)) {
  507. sol_obj_free(index);
  508. index = sol_new_buffer(state, dsl_new_seq_iter(obj->seq), sizeof(dsl_seq_iter), OWN_CALLF, _sol_freef_seq_iter, NULL);
  509. sol_map_set_name(state, local, "idx", index);
  510. sol_obj_free(index);
  511. }
  512. if(dsl_seq_iter_is_invalid(index->buffer)) {
  513. sol_obj_free(index);
  514. sol_obj_free(obj);
  515. sol_obj_free(local);
  516. return sol_incref(state->None);
  517. }
  518. res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer))->key);
  519. dsl_seq_iter_next(index->buffer);
  520. sol_obj_free(local);
  521. sol_obj_free(obj);
  522. return res;
  523. }
  524. sol_object_t *sol_f_ast_print(sol_state_t *state, sol_object_t *args) {
  525. sol_object_t *obj = sol_list_get_index(state, args, 0);
  526. if(sol_is_aststmt(obj)) {
  527. st_print(state, obj->node);
  528. } else {
  529. ex_print(state, obj->node);
  530. }
  531. sol_obj_free(obj);
  532. return sol_incref(state->None);
  533. }
  534. sol_object_t *sol_f_singlet_tostring(sol_state_t *state, sol_object_t *args) {
  535. sol_object_t *obj = sol_list_get_index(state, args, 0), *res = sol_new_string(state, obj->str);
  536. sol_obj_free(obj);
  537. return res;
  538. }
  539. sol_object_t *sol_f_int_add(sol_state_t *state, sol_object_t *args) {
  540. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  541. sol_object_t *res = sol_new_int(state, a->ival + bint->ival);
  542. sol_obj_free(a);
  543. sol_obj_free(b);
  544. if(sol_has_error(state)) {
  545. sol_obj_free(res);
  546. return sol_incref(state->None);
  547. }
  548. return res;
  549. }
  550. sol_object_t *sol_f_int_sub(sol_state_t *state, sol_object_t *args) {
  551. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  552. sol_object_t *res = sol_new_int(state, a->ival - bint->ival);
  553. sol_obj_free(a);
  554. sol_obj_free(b);
  555. if(sol_has_error(state)) {
  556. sol_obj_free(res);
  557. return sol_incref(state->None);
  558. }
  559. return res;
  560. }
  561. sol_object_t *sol_f_int_mul(sol_state_t *state, sol_object_t *args) {
  562. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  563. sol_object_t *res = sol_new_int(state, a->ival * bint->ival);
  564. sol_obj_free(a);
  565. sol_obj_free(b);
  566. if(sol_has_error(state)) {
  567. sol_obj_free(res);
  568. return sol_incref(state->None);
  569. }
  570. return res;
  571. }
  572. sol_object_t *sol_f_int_div(sol_state_t *state, sol_object_t *args) {
  573. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  574. sol_object_t *res = sol_new_int(state, a->ival / bint->ival);
  575. sol_obj_free(a);
  576. sol_obj_free(b);
  577. if(sol_has_error(state)) {
  578. sol_obj_free(res);
  579. return sol_incref(state->None);
  580. }
  581. return res;
  582. }
  583. sol_object_t *sol_f_int_mod(sol_state_t *state, sol_object_t *args) {
  584. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  585. sol_object_t *res = sol_new_int(state, a->ival % bint->ival);
  586. sol_obj_free(a);
  587. sol_obj_free(b);
  588. if(sol_has_error(state)) {
  589. sol_obj_free(res);
  590. return sol_incref(state->None);
  591. }
  592. return res;
  593. }
  594. sol_object_t *sol_f_int_pow(sol_state_t *state, sol_object_t *args) {
  595. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  596. sol_object_t *res = sol_new_int(state, (long) pow((double) a->ival, bint->ival));
  597. sol_obj_free(a);
  598. sol_obj_free(b);
  599. if(sol_has_error(state)) {
  600. sol_obj_free(res);
  601. return sol_incref(state->None);
  602. }
  603. return res;
  604. }
  605. sol_object_t *sol_f_int_band(sol_state_t *state, sol_object_t *args) {
  606. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  607. sol_object_t *res = sol_new_int(state, a->ival & bint->ival);
  608. sol_obj_free(a);
  609. sol_obj_free(b);
  610. if(sol_has_error(state)) {
  611. sol_obj_free(res);
  612. return sol_incref(state->None);
  613. }
  614. return res;
  615. }
  616. sol_object_t *sol_f_int_bor(sol_state_t *state, sol_object_t *args) {
  617. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  618. sol_object_t *res = sol_new_int(state, a->ival | bint->ival);
  619. sol_obj_free(a);
  620. sol_obj_free(b);
  621. if(sol_has_error(state)) {
  622. sol_obj_free(res);
  623. return sol_incref(state->None);
  624. }
  625. return res;
  626. }
  627. sol_object_t *sol_f_int_bxor(sol_state_t *state, sol_object_t *args) {
  628. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  629. sol_object_t *res = sol_new_int(state, a->ival ^ bint->ival);
  630. sol_obj_free(a);
  631. sol_obj_free(b);
  632. if(sol_has_error(state)) {
  633. sol_obj_free(res);
  634. return sol_incref(state->None);
  635. }
  636. return res;
  637. }
  638. sol_object_t *sol_f_int_blsh(sol_state_t *state, sol_object_t *args) {
  639. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  640. sol_object_t *res = sol_new_int(state, a->ival << bint->ival);
  641. sol_obj_free(a);
  642. sol_obj_free(b);
  643. if(sol_has_error(state)) {
  644. sol_obj_free(res);
  645. return sol_incref(state->None);
  646. }
  647. return res;
  648. }
  649. sol_object_t *sol_f_int_brsh(sol_state_t *state, sol_object_t *args) {
  650. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  651. sol_object_t *res = sol_new_int(state, a->ival >> bint->ival);
  652. sol_obj_free(a);
  653. sol_obj_free(b);
  654. if(sol_has_error(state)) {
  655. sol_obj_free(res);
  656. return sol_incref(state->None);
  657. }
  658. return res;
  659. }
  660. sol_object_t *sol_f_int_bnot(sol_state_t *state, sol_object_t *args) {
  661. sol_object_t *a = sol_list_get_index(state, args, 0);
  662. sol_object_t *res = sol_new_int(state, ~a->ival);
  663. sol_obj_free(a);
  664. return res;
  665. }
  666. sol_object_t *sol_f_int_cmp(sol_state_t *state, sol_object_t *args) {
  667. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  668. sol_object_t *res;
  669. if(sol_is_int(b)) {
  670. res = sol_new_int(state, a->ival == b->ival ? 0 : (a->ival < b->ival ? -1 : 1));
  671. } else {
  672. res = sol_new_int(state, 1);
  673. }
  674. sol_obj_free(a);
  675. sol_obj_free(b);
  676. return res;
  677. }
  678. sol_object_t *sol_f_int_toint(sol_state_t *state, sol_object_t *args) {
  679. return sol_list_get_index(state, args, 0);
  680. }
  681. sol_object_t *sol_f_int_tofloat(sol_state_t *state, sol_object_t *args) {
  682. sol_object_t *a = sol_list_get_index(state, args, 0);
  683. sol_object_t *res = sol_new_float(state, (double) a->ival);
  684. sol_obj_free(a);
  685. return res;
  686. }
  687. sol_object_t *sol_f_int_tostring(sol_state_t *state, sol_object_t *args) {
  688. sol_object_t *a = sol_list_get_index(state, args, 0);
  689. char *s = _itoa(a->ival);
  690. sol_object_t *res = sol_new_string(state, s);
  691. sol_obj_free(a);
  692. free(s);
  693. return res;
  694. }
  695. sol_object_t *sol_f_float_add(sol_state_t *state, sol_object_t *args) {
  696. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
  697. sol_object_t *res = sol_new_float(state, a->fval + bflt->fval);
  698. sol_obj_free(a);
  699. sol_obj_free(b);
  700. if(sol_has_error(state)) {
  701. sol_obj_free(res);
  702. return sol_incref(state->None);
  703. }
  704. return res;
  705. }
  706. sol_object_t *sol_f_float_sub(sol_state_t *state, sol_object_t *args) {
  707. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
  708. sol_object_t *res = sol_new_float(state, a->fval - bflt->fval);
  709. sol_obj_free(a);
  710. sol_obj_free(b);
  711. if(sol_has_error(state)) {
  712. sol_obj_free(res);
  713. return sol_incref(state->None);
  714. }
  715. return res;
  716. }
  717. sol_object_t *sol_f_float_mul(sol_state_t *state, sol_object_t *args) {
  718. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
  719. sol_object_t *res = sol_new_float(state, a->fval * bflt->fval);
  720. sol_obj_free(a);
  721. sol_obj_free(b);
  722. if(sol_has_error(state)) {
  723. sol_obj_free(res);
  724. return sol_incref(state->None);
  725. }
  726. return res;
  727. }
  728. sol_object_t *sol_f_float_div(sol_state_t *state, sol_object_t *args) {
  729. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
  730. sol_object_t *res = sol_new_float(state, a->fval / bflt->fval);
  731. sol_obj_free(a);
  732. sol_obj_free(b);
  733. if(sol_has_error(state)) {
  734. sol_obj_free(res);
  735. return sol_incref(state->None);
  736. }
  737. return res;
  738. }
  739. sol_object_t *sol_f_float_pow(sol_state_t *state, sol_object_t *args) {
  740. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bflt = sol_cast_float(state, b);
  741. sol_object_t *res = sol_new_float(state, pow(a->fval, bflt->fval));
  742. sol_obj_free(a);
  743. sol_obj_free(b);
  744. if(sol_has_error(state)) {
  745. sol_obj_free(res);
  746. return sol_incref(state->None);
  747. }
  748. return res;
  749. }
  750. sol_object_t *sol_f_float_cmp(sol_state_t *state, sol_object_t *args) {
  751. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  752. sol_object_t *res;
  753. if(sol_is_float(b)) {
  754. res = sol_new_int(state, a->fval==b->fval? 0 : (a->fval<b->fval? -1 : 1));
  755. } else {
  756. res = sol_new_int(state, 1);
  757. }
  758. sol_obj_free(a);
  759. sol_obj_free(b);
  760. return res;
  761. }
  762. sol_object_t *sol_f_float_toint(sol_state_t *state, sol_object_t *args) {
  763. sol_object_t *a = sol_list_get_index(state, args, 0);
  764. sol_object_t *res = sol_new_int(state, (int) a->fval);
  765. sol_obj_free(a);
  766. return res;
  767. }
  768. sol_object_t *sol_f_float_tofloat(sol_state_t *state, sol_object_t *args) {
  769. return sol_list_get_index(state, args, 0);
  770. }
  771. sol_object_t *sol_f_float_tostring(sol_state_t *state, sol_object_t *args) {
  772. sol_object_t *a = sol_list_get_index(state, args, 0);
  773. char *s = _ftoa(a->fval);
  774. sol_object_t *res = sol_new_string(state, s);
  775. sol_obj_free(a);
  776. free(s);
  777. return res;
  778. }
  779. sol_object_t *sol_f_str_add(sol_state_t *state, sol_object_t *args) {
  780. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bstr = sol_cast_string(state, b);
  781. sol_object_t *res = sol_string_concat(state, a, bstr);
  782. sol_obj_free(a);
  783. sol_obj_free(b);
  784. if(sol_has_error(state)) {
  785. sol_obj_free(res);
  786. return sol_incref(state->None);
  787. }
  788. return res;
  789. }
  790. sol_object_t *sol_f_str_mul(sol_state_t *state, sol_object_t *args) {
  791. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b);
  792. int n = strlen(a->str) * bint->ival + 1;
  793. char *s = malloc(n);
  794. int i;
  795. s[0] = '\0';
  796. for(i = 0; i < b->ival; i++) {
  797. strncat(s, a->str, n);
  798. }
  799. sol_object_t *res = sol_new_string(state, s);
  800. sol_obj_free(a);
  801. sol_obj_free(b);
  802. sol_obj_free(bint);
  803. free(s);
  804. if(sol_has_error(state)) {
  805. sol_obj_free(res);
  806. return sol_incref(state->None);
  807. }
  808. return res;
  809. }
  810. sol_object_t *sol_f_str_cmp(sol_state_t *state, sol_object_t *args) {
  811. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  812. sol_object_t *res;
  813. if(sol_is_string(b)) {
  814. res = sol_new_int(state, strcmp(a->str, b->str));
  815. } else {
  816. res = sol_new_int(state, 1);
  817. }
  818. sol_obj_free(a);
  819. sol_obj_free(b);
  820. return res;
  821. }
  822. sol_object_t *sol_f_str_len(sol_state_t *state, sol_object_t *args) {
  823. sol_object_t *a = sol_list_get_index(state, args, 0);
  824. sol_object_t *res = sol_new_int(state, strlen(a->str));
  825. sol_obj_free(a);
  826. return res;
  827. }
  828. sol_object_t *sol_f_str_index(sol_state_t *state, sol_object_t *args) {
  829. sol_object_t *str = sol_list_get_index(state, args, 0), *key = sol_list_get_index(state, args, 1), *idx, *funcs, *res;
  830. char buf[2] = {0, 0};
  831. if(sol_is_string(key)) {
  832. funcs = sol_get_methods_name(state, "string");
  833. res = sol_map_get(state, funcs, key);
  834. sol_obj_free(funcs);
  835. return res;
  836. }
  837. idx = sol_cast_int(state, key);
  838. if(idx->ival >= 0 && idx->ival < strlen(str->str)) {
  839. buf[0] = str->str[idx->ival];
  840. }
  841. sol_obj_free(str);
  842. sol_obj_free(key);
  843. sol_obj_free(idx);
  844. return sol_new_string(state, buf);
  845. }
  846. sol_object_t *sol_f_str_iter(sol_state_t *state, sol_object_t *args) {
  847. return sol_new_cfunc(state, sol_f_iter_str);
  848. }
  849. sol_object_t *sol_f_str_toint(sol_state_t *state, sol_object_t *args) {
  850. sol_object_t *a = sol_list_get_index(state, args, 0);
  851. sol_object_t *res = sol_new_int(state, atoi(a->str));
  852. sol_obj_free(a);
  853. return res;
  854. }
  855. sol_object_t *sol_f_str_tofloat(sol_state_t *state, sol_object_t *args) {
  856. sol_object_t *a = sol_list_get_index(state, args, 0);
  857. sol_object_t *res = sol_new_float(state, atof(a->str));
  858. sol_obj_free(a);
  859. return res;
  860. }
  861. sol_object_t *sol_f_str_tostring(sol_state_t *state, sol_object_t *args) {
  862. return sol_list_get_index(state, args, 0);
  863. }
  864. sol_object_t *sol_f_str_repr(sol_state_t *state, sol_object_t *args) {
  865. sol_object_t *obj = sol_list_get_index(state, args, 0), *cur = sol_new_string(state, "\""), *next = sol_string_concat(state, cur, obj);
  866. sol_obj_free(cur);
  867. cur = next;
  868. next = sol_string_concat_cstr(state, cur, "\"");
  869. sol_obj_free(cur);
  870. return next;
  871. }
  872. sol_object_t *sol_f_str_sub(sol_state_t *state, sol_object_t *args) {
  873. sol_object_t *str = sol_list_get_index(state, args, 0), *low = sol_list_get_index(state, args, 1), *high = sol_list_get_index(state, args, 2);
  874. sol_object_t *ilow, *ihigh;
  875. long l, h;
  876. size_t len = strlen(str->str), i;
  877. char *s;
  878. if(sol_is_none(state, low)) {
  879. ilow = sol_new_int(state, 0);
  880. } else {
  881. ilow = sol_cast_int(state, low);
  882. }
  883. if(sol_is_none(state, high)) {
  884. ihigh = sol_new_int(state, len);
  885. } else {
  886. ihigh = sol_cast_int(state, high);
  887. }
  888. sol_obj_free(low);
  889. sol_obj_free(high);
  890. l = ilow->ival;
  891. h = ihigh->ival;
  892. sol_obj_free(ihigh);
  893. sol_obj_free(ilow);
  894. if(l < 0) {
  895. l += len;
  896. if(l < 0) {
  897. l = 0;
  898. }
  899. }
  900. if(l > len) {
  901. l = len;
  902. }
  903. if(h < 0) {
  904. h += len;
  905. if(h < 0) {
  906. h = 0;
  907. }
  908. }
  909. if(h > len) {
  910. h = len;
  911. }
  912. if(l >= h) {
  913. sol_obj_free(str);
  914. return sol_new_string(state, "");
  915. }
  916. s = malloc(h - l + 1);
  917. for(i = l; i < h; i++) {
  918. s[i - l] = str->str[i];
  919. }
  920. s[h - l] = '\0';
  921. sol_obj_free(str);
  922. return sol_new_string(state, s);
  923. }
  924. sol_object_t *sol_f_str_split(sol_state_t *state, sol_object_t *args) {
  925. sol_object_t *str = sol_list_get_index(state, args, 0), *tok = sol_list_get_index(state, args, 1), *stok = sol_cast_string(state, tok);
  926. sol_object_t *res = sol_new_list(state), *opart;
  927. char *s = strdup(str->str);
  928. char *part = strtok(s, stok->str);
  929. sol_obj_free(tok);
  930. sol_obj_free(str);
  931. if(!part) {
  932. sol_obj_free(res);
  933. sol_obj_free(stok);
  934. return sol_incref(state->None);
  935. }
  936. opart = sol_new_string(state, part);
  937. sol_list_insert(state, res, 0, opart);
  938. sol_obj_free(opart);
  939. while(part = strtok(NULL, stok->str)) {
  940. opart = sol_new_string(state, part);
  941. sol_list_insert(state, res, sol_list_len(state, res), opart);
  942. sol_obj_free(opart);
  943. }
  944. sol_obj_free(stok);
  945. return res;
  946. }
  947. sol_object_t *sol_f_str_find(sol_state_t *state, sol_object_t *args) {
  948. sol_object_t *str = sol_list_get_index(state, args, 0), *substr = sol_list_get_index(state, args, 1), *ssubstr = sol_cast_string(state, substr);
  949. char *ptr = strstr(str->str, ssubstr->str);
  950. sol_object_t *res = sol_new_int(state, ptr ? ptr - str->str : -1);
  951. sol_obj_free(str);
  952. sol_obj_free(substr);
  953. sol_obj_free(ssubstr);
  954. return res;
  955. }
  956. sol_object_t *sol_f_list_add(sol_state_t *state, sol_object_t *args) {
  957. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ls;
  958. if(!sol_is_list(b)) {
  959. sol_obj_free(a);
  960. sol_obj_free(b);
  961. return sol_set_error_string(state, "Adding list to non-list");
  962. }
  963. ls = sol_list_copy(state, a);
  964. sol_list_append(state, ls, b);
  965. sol_obj_free(a);
  966. sol_obj_free(b);
  967. return ls;
  968. }
  969. sol_object_t *sol_f_list_mul(sol_state_t *state, sol_object_t *args) {
  970. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *bint = sol_cast_int(state, b), *ls;
  971. int i;
  972. if(sol_has_error(state)) {
  973. sol_obj_free(a);
  974. sol_obj_free(b);
  975. sol_obj_free(bint);
  976. return sol_incref(state->None);
  977. }
  978. ls = sol_new_list(state);
  979. for(i = 0; i < b->ival; i++) {
  980. sol_list_append(state, ls, a);
  981. if(sol_has_error(state)) {
  982. sol_obj_free(a);
  983. sol_obj_free(b);
  984. sol_obj_free(bint);
  985. return sol_incref(state->None);
  986. }
  987. }
  988. return ls;
  989. }
  990. sol_object_t *sol_f_list_cmp(sol_state_t *state, sol_object_t *args) {
  991. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *item, *ls, *tmp;
  992. int i, alen, blen;
  993. if(!sol_is_list(b)) {
  994. sol_obj_free(b);
  995. sol_obj_free(a);
  996. return sol_new_int(state, 1); // XXX lists always greater than non-lists?
  997. }
  998. alen = sol_list_len(state, a);
  999. blen = sol_list_len(state, b);
  1000. if(alen != blen) {
  1001. sol_obj_free(b);
  1002. sol_obj_free(a);
  1003. return sol_new_int(state, alen > blen ? 1 : -1);
  1004. }
  1005. ls = sol_new_list(state);
  1006. sol_list_insert(state, ls, 0, state->None);
  1007. sol_list_insert(state, ls, 1, state->None);
  1008. for(i = 0; i < alen; i++) {
  1009. tmp = sol_list_get_index(state, a, i);
  1010. sol_list_set_index(state, ls, 0, tmp);
  1011. item = sol_list_get_index(state, b, i);
  1012. sol_list_set_index(state, ls, 1, item);
  1013. sol_obj_free(item);
  1014. item = CALL_METHOD(state, tmp, cmp, ls);
  1015. sol_obj_free(tmp);
  1016. if(item->ival != 0) {
  1017. sol_obj_free(ls);
  1018. sol_obj_free(b);
  1019. sol_obj_free(a);
  1020. return item;
  1021. }
  1022. sol_obj_free(item);
  1023. }
  1024. sol_obj_free(ls);
  1025. sol_obj_free(b);
  1026. sol_obj_free(a);
  1027. return sol_new_int(state, 0);
  1028. }
  1029. sol_object_t *sol_f_list_index(sol_state_t *state, sol_object_t *args) {
  1030. sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *ival;
  1031. sol_object_t *res, *funcs;
  1032. if(sol_is_string(b)) {
  1033. funcs = sol_get_methods_name(state, "list");
  1034. res = sol_map_get(state, funcs, b);
  1035. sol_obj_free(funcs);
  1036. } else {
  1037. ival = sol_cast_int(state, b);
  1038. res = sol_list_get_index(state, ls, ival->ival);
  1039. sol_obj_free(ival);
  1040. }
  1041. sol_obj_free(ls);
  1042. sol_obj_free(b);
  1043. return res;
  1044. }
  1045. sol_object_t *sol_f_list_setindex(sol_state_t *state, sol_object_t *args) {
  1046. sol_object_t *ls = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args ,1), *bint = sol_cast_int(state, b);
  1047. sol_object_t *val = sol_list_get_index(state, args, 2);
  1048. sol_list_set_index(state, ls, bint->ival, val);
  1049. sol_obj_free(ls);
  1050. sol_obj_free(b);
  1051. sol_obj_free(bint);
  1052. sol_obj_free(val);
  1053. return sol_incref(state->None);
  1054. }
  1055. sol_object_t *sol_f_list_len(sol_state_t *state, sol_object_t *args) {
  1056. sol_object_t *ls = sol_list_get_index(state, args, 0);
  1057. sol_object_t *res = sol_new_int(state, sol_list_len(state, ls));
  1058. sol_obj_free(ls);
  1059. return res;
  1060. }
  1061. sol_object_t *sol_f_list_iter(sol_state_t *state, sol_object_t *args) {
  1062. return sol_new_cfunc(state, sol_f_iter_list);
  1063. }
  1064. sol_ob