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.

3222 lines
96 KiB

  1. #define _GNU_SOURCE
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <stdint.h>
  7. #include <dlfcn.h>
  8. #ifndef NO_READLINE
  9. #include <readline/readline.h>
  10. #include <readline/history.h>
  11. #endif
  12. #include <termios.h>
  13. #include <sys/ioctl.h>
  14. #include "ast.h"
  15. #include "dsl/dsl.h"
  16. // XXX hardcoded buffer sizes
  17. #define STDIO_CHUNK_SIZE 4096
  18. static char *_itoa(int i) {
  19. int n = 33;
  20. char *s = malloc(n);
  21. snprintf(s, n, "%d", i);
  22. return s;
  23. }
  24. static char *_ftoa(double f) {
  25. int n = 65;
  26. char *s = malloc(n);
  27. snprintf(s, n, "%f", f);
  28. return s;
  29. }
  30. sol_object_t *sol_f_not_impl(sol_state_t *state, sol_object_t *args) {
  31. char buffer[64];
  32. snprintf(buffer, 64, "Undefined method (%s on %s)", state->calling_meth, state->calling_type);
  33. return sol_set_error_string(state, buffer);
  34. }
  35. sol_object_t *sol_f_default_cmp(sol_state_t *state, sol_object_t *args) {
  36. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  37. sol_object_t *res = sol_new_int(state, a != b);
  38. sol_obj_free(a);
  39. sol_obj_free(b);
  40. return res;
  41. }
  42. sol_object_t *sol_f_default_tostring(sol_state_t *state, sol_object_t *args) {
  43. sol_object_t *obj = sol_list_get_index(state, args, 0);
  44. char s[64];
  45. snprintf(s, 64, "<%s object at %p>", obj->ops->tname, obj);
  46. sol_obj_free(obj);
  47. return sol_new_string(state, s);
  48. }
  49. sol_object_t *sol_f_default_repr(sol_state_t *state, sol_object_t *args) {
  50. sol_object_t *obj = sol_list_get_index(state, args, 0), *res = CALL_METHOD(state, obj, tostring, args);
  51. sol_obj_free(obj);
  52. return res;
  53. }
  54. sol_object_t *sol_f_default_tobuffer(sol_state_t *state, sol_object_t *args) {
  55. sol_object_t *obj = sol_list_get_index(state, args, 0), *str = CALL_METHOD(state, obj, tostring, args);
  56. sol_object_t *res = sol_new_buffer(state, strdup(str->str), strlen(str->str), OWN_FREE, NULL, NULL);
  57. sol_obj_free(obj);
  58. sol_obj_free(str);
  59. return res;
  60. }
  61. sol_object_t *sol_f_tbang(sol_state_t *state, sol_object_t *args) {
  62. sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1);
  63. int refa = a->refcnt, refb = b->refcnt;
  64. sol_object_t c = *b;
  65. *b = *a;
  66. *a = c;
  67. b->refcnt = refa;
  68. a->refcnt = refb;
  69. sol_obj_free(a);
  70. sol_obj_free(b);
  71. return sol_incref(state->None);
  72. }
  73. sol_object_t *sol_f_no_op(sol_state_t *state, sol_object_t *args) {
  74. if(state) {
  75. return sol_incref(state->None);
  76. }
  77. return NULL;
  78. }
  79. sol_object_t *sol_f_toint(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, toint, args);
  82. sol_obj_free(obj);
  83. return res;
  84. }
  85. sol_object_t *sol_f_tofloat(sol_state_t *state, sol_object_t *args) {
  86. sol_object_t *obj = sol_list_get_index(state, args, 0);
  87. sol_object_t *res = CALL_METHOD(state, obj, tofloat, args);
  88. sol_obj_free(obj);
  89. return res;
  90. }
  91. sol_object_t *sol_f_tostring(sol_state_t *state, sol_object_t *args) {
  92. sol_object_t *obj = sol_list_get_index(state, args, 0);
  93. sol_object_t *res = CALL_METHOD(state, obj, tostring, args);
  94. sol_obj_free(obj);
  95. return res;
  96. }
  97. sol_object_t *sol_f_tobuffer(sol_state_t *state, sol_object_t *args) {
  98. sol_object_t *obj = sol_list_get_index(state, args, 0);
  99. sol_object_t *res = CALL_METHOD(state, obj, tobuffer, args);
  100. sol_obj_free(obj);
  101. return res;
  102. }
  103. sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
  104. sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
  105. sol_object_t *ls = sol_new_list(state), *one = sol_new_int(state, 1);
  106. sol_object_t *res;
  107. sol_list_insert(state, fargs, 0, func);
  108. res = CALL_METHOD(state, func, call, fargs);
  109. sol_obj_free(func);
  110. sol_obj_free(fargs);
  111. if(sol_has_error(state)) {
  112. sol_object_t *err = sol_get_error(state);
  113. sol_clear_error(state);
  114. sol_object_t *zero = sol_new_int(state, 0);
  115. sol_obj_free(res);
  116. sol_obj_free(one);
  117. sol_list_insert(state, ls, 0, err);
  118. sol_obj_free(err);
  119. sol_list_insert(state, ls, 0, zero);
  120. sol_obj_free(zero);
  121. sol_list_insert(state, ls, 2, state->traceback);
  122. sol_obj_free(state->traceback);
  123. state->traceback = NULL;
  124. return ls;
  125. }
  126. sol_list_insert(state, ls, 0, res);
  127. sol_obj_free(res);
  128. sol_list_insert(state, ls, 0, one);
  129. sol_obj_free(one);
  130. return ls;
  131. }
  132. sol_object_t *sol_f_apply(sol_state_t *state, sol_object_t *args) {
  133. 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);
  134. if(!sol_is_list(arglist)) {
  135. sol_obj_free(func);
  136. sol_obj_free(arglist);
  137. sol_obj_free(rest);
  138. return sol_set_error_string(state, "apply with non-list");
  139. }
  140. sol_list_append(state, rest, arglist);
  141. sol_obj_free(arglist);
  142. sol_list_insert(state, rest, 0, func);
  143. sol_object_t *res = CALL_METHOD(state, func, call, rest);
  144. sol_obj_free(rest);
  145. sol_obj_free(func);
  146. return res;
  147. }
  148. sol_object_t *sol_f_error(sol_state_t *state, sol_object_t *args) {
  149. sol_object_t *arg = sol_list_get_index(state, args, 0), *res;
  150. res = sol_set_error(state, arg);
  151. sol_obj_free(arg);
  152. return res;
  153. }
  154. sol_object_t *sol_f_type(sol_state_t *state, sol_object_t *args) {
  155. sol_object_t *obj = sol_list_get_index(state, args, 0);
  156. sol_object_t *res = sol_new_buffer(state, strdup(obj->ops->tname), strlen(obj->ops->tname), OWN_FREE, NULL, NULL);
  157. sol_obj_free(obj);
  158. return res;
  159. }
  160. static dsl_seq *seen = NULL;
  161. int test_seen(sol_object_t *obj) {
  162. dsl_seq_iter *iter;
  163. if(seen) {
  164. iter = dsl_new_seq_iter(seen);
  165. while(!dsl_seq_iter_is_invalid(iter)) {
  166. if(dsl_seq_iter_at(iter) == obj) {
  167. return 1;
  168. }
  169. dsl_seq_iter_next(iter);
  170. }
  171. dsl_free_seq_iter(iter);
  172. dsl_seq_insert(seen, dsl_seq_len(seen), obj);
  173. }
  174. return 0;
  175. }
  176. void ob_print(sol_object_t *obj) {
  177. sol_object_t *cur;
  178. dsl_seq_iter *iter;
  179. int i;
  180. if(test_seen(obj)) {
  181. return;
  182. }
  183. switch(obj->type) {
  184. case SOL_SINGLET:
  185. printf("%s", obj->str);
  186. break;
  187. case SOL_INTEGER:
  188. printf("%ld", obj->ival);
  189. break;
  190. case SOL_FLOAT:
  191. printf("%f", obj->fval);
  192. break;
  193. case SOL_STRING:
  194. printf("\"%s\"", obj->str);
  195. break;
  196. case SOL_LIST:
  197. printf("[");
  198. iter = dsl_new_seq_iter(obj->seq);
  199. while(!dsl_seq_iter_is_invalid(iter)) {
  200. ob_print(dsl_seq_iter_at(iter));
  201. printf(", ");
  202. dsl_seq_iter_next(iter);
  203. }
  204. dsl_free_seq_iter(iter);
  205. printf("]");
  206. break;
  207. case SOL_MCELL:
  208. printf("<<");
  209. ob_print(obj->key);
  210. printf("=");
  211. ob_print(obj->val);
  212. printf(">>");
  213. case SOL_MAP:
  214. printf("{");
  215. iter = dsl_new_seq_iter(obj->seq);
  216. while(!dsl_seq_iter_is_invalid(iter)) {
  217. printf("[");
  218. ob_print(AS_OBJ(dsl_seq_iter_at(iter))->key);
  219. printf("] = ");
  220. ob_print(AS_OBJ(dsl_seq_iter_at(iter))->val);
  221. printf(", ");
  222. dsl_seq_iter_next(iter);
  223. }
  224. dsl_free_seq_iter(iter);
  225. printf("}");
  226. break;
  227. case SOL_FUNCTION:
  228. if(obj->fname) {
  229. printf("<Function %s>", obj->fname);
  230. } else {
  231. printf("<Function>");
  232. }
  233. break;
  234. case SOL_CFUNCTION:
  235. printf("<CFunction>");
  236. break;
  237. case SOL_STMT:
  238. st_print(NULL, obj->node); //TODO: FIXME
  239. break;
  240. case SOL_EXPR:
  241. ex_print(NULL, obj->node); //TODO: FIXME
  242. break;
  243. case SOL_BUFFER:
  244. /*
  245. if(obj->sz == -1) {
  246. printf("<Buffer @%p>", obj->buffer);
  247. } else {
  248. printf("<Buffer @%p size %ld>", obj->buffer, obj->sz);
  249. }
  250. */
  251. fwrite(obj->buffer, sizeof(char), obj->sz, stdout);
  252. break;
  253. case SOL_CDATA:
  254. printf("<CData>");
  255. break;
  256. /*default:
  257. cur = sol_cast_string(state, obj);
  258. printf("%s", cur->str);
  259. sol_obj_free(cur);*/
  260. }
  261. }
  262. sol_object_t *sol_f_prepr(sol_state_t *state, sol_object_t *args) {
  263. int i, sz = sol_list_len(state, args);
  264. sol_object_t *obj, *str;
  265. seen = dsl_seq_new_array(NULL, NULL);
  266. for(i = 0; i < sz; i++) {
  267. obj = sol_list_get_index(state, args, i);
  268. str = sol_cast_repr(state, obj);
  269. sol_printf(state, "%s", str->str);
  270. sol_printf(state, " ");
  271. sol_obj_free(obj);
  272. sol_obj_free(str);
  273. }
  274. sol_printf(state, "\n");
  275. printf("\n");
  276. dsl_free_seq(seen);
  277. seen = NULL;
  278. return sol_incref(state->None);
  279. }
  280. sol_object_t *sol_f_print(sol_state_t *state, sol_object_t *args) {
  281. int i, sz = sol_list_len(state, args);
  282. sol_object_t *obj, *str;
  283. seen = dsl_seq_new_array(NULL, NULL);
  284. for(i = 0; i < sz; i++) {
  285. obj = sol_list_get_index(state, args, i);
  286. str = sol_cast_string(state, obj);
  287. sol_printf(state, "%s", str->str);
  288. sol_printf(state, " ");
  289. sol_obj_free(obj);
  290. sol_obj_free(str);
  291. }
  292. sol_printf(state, "\n");
  293. dsl_free_seq(seen);
  294. seen = NULL;
  295. return sol_incref(state->None);
  296. }
  297. sol_object_t *sol_f_rawget(sol_state_t *state, sol_object_t *args) {
  298. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *res;
  299. if(!sol_is_map(obj)) {
  300. return sol_set_error_string(state, "Rawset of non-map");
  301. }
  302. key = sol_list_get_index(state, args, 1);
  303. res = sol_map_get(state, obj, key);
  304. sol_obj_free(key);
  305. sol_obj_free(obj);
  306. return res;
  307. }
  308. sol_object_t *sol_f_rawset(sol_state_t *state, sol_object_t *args) {
  309. sol_object_t *obj = sol_list_get_index(state, args, 0), *key, *val;
  310. if(!sol_is_map(obj)) {
  311. return sol_set_error_string(state, "Rawset of non-map");
  312. }
  313. key = sol_list_get_index(state, args, 1);
  314. val = sol_list_get_index(state, args, 2);
  315. sol_map_set(state, obj, key, val);
  316. sol_obj_free(val);
  317. sol_obj_free(key);
  318. sol_obj_free(obj);
  319. return sol_incref(state->None);
  320. }
  321. sol_object_t *sol_f_range(sol_state_t *state, sol_object_t *args) {
  322. sol_object_t *res = sol_new_list(state), *bound = sol_list_get_index(state, args, 0);
  323. sol_object_t *boundi = sol_cast_int(state, bound);
  324. int i;
  325. sol_obj_free(bound);
  326. if(sol_has_error(state)) {
  327. sol_obj_free(boundi);
  328. sol_obj_free(res);
  329. return sol_incref(state->None);
  330. }
  331. for(i = 0; i < boundi->ival; i++) {
  332. sol_list_insert(state, res, sol_list_len(state, res), sol_new_int(state, i));
  333. }
  334. sol_obj_free(boundi);
  335. return res;
  336. }
  337. /*
  338. sol_object_t *sol_f_exec(sol_state_t *state, sol_object_t *args) {
  339. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  340. stmt_node *program;
  341. program = sol_compile(prgstr->str);
  342. if(!program) {
  343. return sol_set_error_string(state, "Compilation failure");
  344. }
  345. // XXX should st_free(program);
  346. sol_exec(state, program);
  347. return sol_incref(state->None);
  348. }
  349. sol_object_t *sol_f_eval(sol_state_t *state, sol_object_t *args) {
  350. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  351. stmt_node *program;
  352. program = sol_compile(prgstr->str);
  353. if(!program) {
  354. return sol_set_error_string(state, "Compilation failure");
  355. }
  356. if(program->type != ST_LIST || program->stmtlist->stmt->type != ST_EXPR) {
  357. return sol_set_error_string(state, "Not an expression");
  358. }
  359. // XXX should st_free(program);
  360. return sol_eval(state, program->stmtlist->stmt->expr);
  361. }
  362. */
  363. sol_object_t *sol_f_execfile(sol_state_t *state, sol_object_t *args) {
  364. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr = sol_cast_string(state, prg);
  365. stmt_node *program;
  366. FILE *f = fopen(prgstr->str, "r");
  367. char *s;
  368. long sz;
  369. if(!f) {
  370. return sol_set_error_string(state, "File open failure");
  371. }
  372. fseek(f, 0, SEEK_END);
  373. sz = ftell(f);
  374. fseek(f, 0, SEEK_SET);
  375. s = malloc(sz + 1);
  376. if(!s) {
  377. fclose(f);
  378. return sol_set_error_string(state, "File memory allocation failure");
  379. }
  380. fread(s, 1, sz, f);
  381. s[sz] = 0;
  382. fclose(f);
  383. program = sol_compile(s);
  384. free(s);
  385. if(!program) {
  386. return sol_set_error_string(state, "Compilation failure");
  387. }
  388. sol_exec(state, program);
  389. st_free(program);
  390. return sol_incref(state->None);
  391. }
  392. sol_object_t *sol_f_parse(sol_state_t *state, sol_object_t *args) {
  393. sol_object_t *prg = sol_list_get_index(state, args, 0), *prgstr;
  394. stmt_node *program;
  395. if(sol_is_buffer(prg)) {
  396. if(prg->sz >= 0) {
  397. program = sol_compile_buffer(prg->buffer, prg->sz);
  398. } else {
  399. sol_obj_free(prg);
  400. return sol_set_error_string(state, "parse unsized buffer");
  401. }
  402. } else {
  403. prgstr = sol_cast_string(state, prg);
  404. program = sol_compile(prgstr->str);
  405. sol_obj_free(prgstr);
  406. }
  407. sol_obj_free(prg);
  408. if(!program) {
  409. return sol_set_error_string(state, "Compilation failure");
  410. }
  411. return sol_new_stmtnode(state, program);
  412. }
  413. sol_object_t *sol_f_ord(sol_state_t *state, sol_object_t *args) {
  414. sol_object_t *arg = sol_list_get_index(state, args, 0), *str = sol_cast_string(state, arg);
  415. sol_object_t *arg2, *iarg, *res;
  416. long idx = 0;
  417. size_t len = strlen(str->str);
  418. sol_obj_free(arg);
  419. if(sol_list_len(state, args) > 1) {
  420. arg2 = sol_list_get_index(state, args, 1);
  421. iarg = sol_cast_int(state, arg2);
  422. sol_obj_free(arg2);
  423. idx = iarg->ival;
  424. sol_obj_free(iarg);
  425. }
  426. if(idx < 0) {
  427. idx += len;
  428. }
  429. if(idx < 0 || idx >= len) {
  430. sol_obj_free(str);
  431. return sol_set_error_string(state, "Compute ord of out-of-bounds index");
  432. }
  433. res = sol_new_int(state, str->str[idx]);
  434. sol_obj_free(str);
  435. return res;
  436. }
  437. sol_object_t *sol_f_chr(sol_state_t *state, sol_object_t *args) {
  438. sol_object_t *arg = sol_list_get_index(state, args, 0), *iarg = sol_cast_int(state, arg);
  439. char cbuf[2] = {iarg->ival, 0};
  440. sol_object_t *res = sol_new_buffer(state, strdup(cbuf), 1, OWN_FREE, NULL, NULL);
  441. sol_obj_free(arg);
  442. sol_obj_free(iarg);
  443. return res;
  444. }
  445. sol_object_t *sol_f_debug_getref(sol_state_t *state, sol_object_t *args) {
  446. sol_object_t *obj = sol_list_get_index(state, args, 0);
  447. 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.
  448. sol_obj_free(obj);
  449. return res;
  450. }
  451. sol_object_t *sol_f_debug_setref(sol_state_t *state, sol_object_t *args) {
  452. sol_object_t *obj = sol_list_get_index(state, args, 0), *cnt = sol_list_get_index(state, args, 1);
  453. obj->refcnt = sol_cast_int(state, cnt)->ival + 2; // NB: As above.
  454. sol_obj_free(cnt);
  455. sol_obj_free(obj);
  456. return sol_incref(state->None);
  457. }
  458. sol_object_t *sol_f_debug_closure(sol_state_t *state, sol_object_t *args) {
  459. sol_object_t *func = sol_list_get_index(state, args, 0);
  460. sol_object_t *res = sol_incref(func->closure);
  461. sol_obj_free(func);
  462. return res;
  463. }
  464. sol_object_t *sol_f_debug_globals(sol_state_t *state, sol_object_t *args) {
  465. return sol_list_get_index(state, state->scopes, sol_list_len(state, state->scopes) - 1);
  466. }
  467. sol_object_t *sol_f_debug_locals(sol_state_t *state, sol_object_t *args) {
  468. return sol_list_get_index(state, state->scopes, 0);
  469. }
  470. sol_object_t *sol_f_debug_scopes(sol_state_t *state, sol_object_t *args) {
  471. return sol_incref(state->scopes);
  472. }
  473. sol_object_t *sol_f_debug_getops(sol_state_t *state, sol_object_t *args) {
  474. sol_object_t *obj = sol_list_get_index(state, args, 0), *res = sol_new_map(state);
  475. sol_map_borrow_name(state, res, "name", sol_new_buffer(state, obj->ops->tname, strlen(obj->ops->tname), OWN_NONE, NULL, NULL));
  476. sol_map_borrow_name(state, res, "flags", sol_new_int(state, obj->ops->tflags));
  477. sol_map_borrow_name(state, res, "add", sol_new_cfunc(state, obj->ops->add, "add"));
  478. sol_map_borrow_name(state, res, "sub", sol_new_cfunc(state, obj->ops->sub, "sub"));
  479. sol_map_borrow_name(state, res, "mul", sol_new_cfunc(state, obj->ops->mul, "mul"));
  480. sol_map_borrow_name(state, res, "div", sol_new_cfunc(state, obj->ops->div, "div"));
  481. sol_map_borrow_name(state, res, "mod", sol_new_cfunc(state, obj->ops->mod, "mod"));
  482. sol_map_borrow_name(state, res, "pow", sol_new_cfunc(state, obj->ops->pow, "pow"));
  483. sol_map_borrow_name(state, res, "tbang", sol_new_cfunc(state, obj->ops->tbang, "tbang"));
  484. sol_map_borrow_name(state, res, "band", sol_new_cfunc(state, obj->ops->band, "band"));
  485. sol_map_borrow_name(state, res, "bor", sol_new_cfunc(state, obj->ops->bor, "bor"));
  486. sol_map_borrow_name(state, res, "bxor", sol_new_cfunc(state, obj->ops->bxor, "bxor"));
  487. sol_map_borrow_name(state, res, "blsh", sol_new_cfunc(state, obj->ops->blsh, "blsh"));
  488. sol_map_borrow_name(state, res, "brsh", sol_new_cfunc(state, obj->ops->brsh, "brsh"));
  489. sol_map_borrow_name(state, res, "bnot", sol_new_cfunc(state, obj->ops->bnot, "bnot"));
  490. sol_map_borrow_name(state, res, "cmp", sol_new_cfunc(state, obj->ops->cmp, "cmp"));
  491. sol_map_borrow_name(state, res, "call", sol_new_cfunc(state, obj->ops->call, "call"));
  492. sol_map_borrow_name(state, res, "index", sol_new_cfunc(state, obj->ops->index, "index"));
  493. sol_map_borrow_name(state, res, "setindex", sol_new_cfunc(state, obj->ops->setindex, "setindex"));
  494. sol_map_borrow_name(state, res, "len", sol_new_cfunc(state, obj->ops->len, "len"));
  495. sol_map_borrow_name(state, res, "iter", sol_new_cfunc(state, obj->ops->iter, "iter"));
  496. sol_map_borrow_name(state, res, "toint", sol_new_cfunc(state, obj->ops->toint, "toint"));
  497. sol_map_borrow_name(state, res, "tofloat", sol_new_cfunc(state, obj->ops->tofloat, "tofloat"));
  498. sol_map_borrow_name(state, res, "tostring", sol_new_cfunc(state, obj->ops->tostring, "tostring"));
  499. sol_map_borrow_name(state, res, "tobuffer", sol_new_cfunc(state, obj->ops->tobuffer, "tobuffer"));
  500. sol_map_borrow_name(state, res, "repr", sol_new_cfunc(state, obj->ops->repr, "repr"));
  501. sol_map_borrow_name(state, res, "init", sol_new_cfunc(state, obj->ops->init, "init"));
  502. sol_map_borrow_name(state, res, "free", sol_new_cfunc(state, obj->ops->free, "free"));
  503. sol_obj_free(obj);
  504. return res;
  505. }
  506. #ifndef NO_READLINE
  507. sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
  508. sol_object_t *obj, *objstr, *res;
  509. char *line;
  510. if(sol_list_len(state, args) > 0) {
  511. obj = sol_list_get_index(state, args, 0);
  512. objstr = sol_cast_string(state, obj);
  513. line = readline(objstr->str);
  514. sol_obj_free(obj);
  515. sol_obj_free(objstr);
  516. } else {
  517. line = readline("");
  518. }
  519. if(line) {
  520. res = sol_new_buffer(state, strdup(line), strlen(line), OWN_FREE, NULL, NULL);
  521. free(line);
  522. } else {
  523. res = sol_new_buffer(state, strdup(""), 0, OWN_FREE, NULL, NULL);
  524. }
  525. return res;
  526. }
  527. sol_object_t *sol_f_readline_add_history(sol_state_t *state, sol_object_t *args) {
  528. sol_object_t *line = sol_list_get_index(state, args, 0), *linestr = sol_cast_string(state, line);
  529. add_history(linestr->str);
  530. sol_obj_free(linestr);
  531. sol_obj_free(line);
  532. return sol_incref(state->None);
  533. }
  534. #endif
  535. void _sol_freef_seq_iter(void *iter, size_t sz) {
  536. dsl_free_seq_iter((dsl_seq_iter *) iter);
  537. }
  538. sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
  539. sol_object_t *obj = sol_list_get_index(state, args, 0), *local = sol_list_get_index(state, args, 1);
  540. sol_object_t *index = sol_map_get_name(state, local, "idx"), *max = sol_map_get_name(state, local, "sz"), *res;
  541. char temp[2] = {0, 0};
  542. if(sol_is_none(state, index) || sol_is_none(state, max)) {
  543. sol_obj_free(index);
  544. index = sol_new_buffer(state, (void *) 0, sizeof(void *), OWN_NONE, NULL, NULL);
  545. sol_map_set_name(state, local, "idx", index);
  546. sol_obj_free(max);
  547. max = sol_new_int(state, strlen(obj->str));
  548. sol_map_set_name(state, local, "sz", max);
  549. }
  550. if(((size_t) index->buffer) >= max->ival) {
  551. sol_obj_free(index);
  552. sol_obj_free(obj);
  553. sol_obj_free