Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

1348 строки
52 KiB

  1. namespace Slime {
  2. proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool {
  3. if (n1 == n2)
  4. return true;
  5. if (n1->type != n2->type)
  6. return false;
  7. switch (n1->type) {
  8. case Lisp_Object_Type::T:
  9. case Lisp_Object_Type::Nil:
  10. case Lisp_Object_Type::Symbol:
  11. case Lisp_Object_Type::Keyword:
  12. case Lisp_Object_Type::Function:
  13. // QUESTION(Felix): should a pointer
  14. // object compare the pointer?
  15. case Lisp_Object_Type::Pointer:
  16. case Lisp_Object_Type::Continuation: return false;
  17. case Lisp_Object_Type::Number: return n1->value.number == n2->value.number;
  18. case Lisp_Object_Type::String: return string_equal(n1->value.string, n2->value.string);
  19. case Lisp_Object_Type::Pair: {
  20. return lisp_object_equal(n1->value.pair.first, n2->value.pair.first) &&
  21. lisp_object_equal(n1->value.pair.rest, n2->value.pair.rest);
  22. } break;
  23. case Lisp_Object_Type::HashMap: {
  24. auto n1_keys = n1->value.hashMap->get_all_keys();
  25. auto n2_keys = n2->value.hashMap->get_all_keys();
  26. defer {
  27. n1_keys.dealloc();
  28. n2_keys.dealloc();
  29. };
  30. if (n1_keys.next_index != n2_keys.next_index)
  31. return false;
  32. n1_keys.sort();
  33. n2_keys.sort();
  34. for (u32 i = 0; i < n1_keys.next_index; ++i) {
  35. if (!lisp_object_equal(n1_keys[i], n2_keys[i]))
  36. return false;
  37. if (!lisp_object_equal(n1->value.hashMap->get_object(n1_keys[i]),
  38. n2->value.hashMap->get_object(n2_keys[i])))
  39. return false;
  40. }
  41. return true;
  42. }
  43. case Lisp_Object_Type::Vector: {
  44. if (n1->value.vector.length != n2->value.vector.length )
  45. return false;
  46. for (u32 i = 0; i < n1->value.vector.length; ++i) {
  47. if (!lisp_object_equal(n1->value.vector.data+i, n2->value.vector.data+i))
  48. return false;
  49. }
  50. return true;
  51. } break;
  52. default: create_not_yet_implemented_error();
  53. }
  54. // we should never reach here
  55. return false;
  56. }
  57. proc add_to_load_path(const path_char* path) -> void {
  58. using Globals::load_path;
  59. load_path.append((path_char*)path);
  60. }
  61. proc built_in_load(String file_name) -> Lisp_Object* {
  62. profile_with_comment(file_name.data);
  63. char* file_content;
  64. path_char fullpath[MAX_PATH];
  65. #ifdef UNICODE
  66. path_char* temp = char_to_path_char(Memory::get_c_str(file_name));
  67. swprintf(fullpath, MAX_PATH,L"%s", temp);
  68. file_content = read_entire_file(temp);
  69. free(temp);
  70. #else
  71. sprintf(fullpath, "%s", Memory::get_c_str(file_name));
  72. file_content = read_entire_file(Memory::get_c_str(file_name));
  73. #endif
  74. if (!file_content) {
  75. for (auto it: Globals::load_path) {
  76. #ifdef UNICODE
  77. fullpath[0] = L'\0';
  78. path_char* temp = char_to_path_char(Memory::get_c_str(file_name));
  79. swprintf(fullpath, MAX_PATH, L"%s%s", it, temp);
  80. free(temp);
  81. #else
  82. fullpath[0] = '\0';
  83. sprintf(fullpath, "%s%s", it, Memory::get_c_str(file_name));
  84. #endif
  85. file_content = read_entire_file(fullpath);
  86. if (file_content)
  87. break;
  88. }
  89. if (!file_content) {
  90. printf("Load path:\n");
  91. for (auto it : Globals::load_path) {
  92. printf(" - %s\n", (char*) it);
  93. }
  94. create_generic_error("The file to load '%s' was not found in the load path.",
  95. Memory::get_c_str(file_name));
  96. return nullptr;
  97. }
  98. }
  99. Lisp_Object* result = Memory::nil;
  100. Array_List<Lisp_Object*>* program;
  101. #ifdef UNICODE
  102. char* temp_c = path_char_to_char(fullpath);
  103. String spath = Memory::create_string(temp_c);
  104. free(temp_c);
  105. #else
  106. String spath = Memory::create_string(fullpath);
  107. #endif
  108. defer {
  109. free(spath.data);
  110. };
  111. try program = Parser::parse_program(spath, file_content);
  112. // NOTE(Felix): deferred so even if the eval failes, it will
  113. // run
  114. defer {
  115. program->dealloc();
  116. free(program);
  117. free(file_content);
  118. };
  119. for (auto expr : *program) {
  120. try result = eval_expr(expr);
  121. }
  122. return result;
  123. }
  124. proc built_in_import(String file_name) -> Lisp_Object* {
  125. profile_this();
  126. Environment* new_env;
  127. try assert("You cannot use import inside of the root-env (parent cycle)",
  128. get_root_environment() != get_current_environment());
  129. new_env = Memory::file_to_env_map.get_object(Memory::get_c_str(file_name));
  130. if (!new_env) {
  131. // create new empty environment
  132. try new_env = Memory::create_child_environment(get_root_environment());
  133. // TODO(Felix): check absoulute paths in the map, not just
  134. // relative ones
  135. Memory::file_to_env_map.set_object(Memory::get_c_str(file_name), new_env);
  136. push_environment(new_env);
  137. defer {
  138. pop_environment();
  139. };
  140. Lisp_Object* res;
  141. try res = built_in_load(file_name);
  142. }
  143. get_current_environment()->parents.append(new_env);
  144. return Memory::nil;
  145. }
  146. proc load_built_ins_into_environment() -> void* {
  147. profile_this();
  148. String file_name_built_ins = Memory::create_string(__FILE__);
  149. defer_free(file_name_built_ins.data);
  150. define_macro((call/cc fun), "TODO") {
  151. profile_with_name("(call/cc)");
  152. using Globals::Current_Execution;
  153. Lisp_Object* args = Current_Execution.pcs[--Current_Execution.pcs.next_index];
  154. try_void assert_list_length(args, 1);
  155. Lisp_Object* fun = args->value.pair.first;
  156. // 2. push cont on the stack and call, the fun is already
  157. // there
  158. Current_Execution.ats.append([] {
  159. try_void assert_type(Current_Execution.cs.data[Current_Execution.cs.next_index-1]
  160. , Lisp_Object_Type::Function);
  161. Lisp_Object* cont = Memory::create_lisp_object_continuation();
  162. Current_Execution.ams.append(Current_Execution.cs.next_index-1);
  163. Current_Execution.pcs.append(Memory::nil);
  164. --cont->value.continuation->cs.next_index;
  165. Current_Execution.cs.append(cont);
  166. (Current_Execution.nass.end()-1)->append(NasAction::Step);
  167. });
  168. (Current_Execution.nass.end()-1)->append(NasAction::And_Then_Action);
  169. // 1. resolve the function
  170. Current_Execution.cs.append(fun);
  171. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  172. };
  173. define_macro((set! sym val), "TODO") {
  174. // NOTE(Felix): This COULD be a define_special in theory,
  175. // but because of call/cc, it cannot be anymore because
  176. // the define_symbol would not be a part of the
  177. // continuation. This happens for example in:
  178. /**
  179. (set! res (+ 2 (call/cc (lambda (cont)
  180. (set! add-5 cont) 1))
  181. 3))
  182. */
  183. // So if 'set! WAS a define_special, then the param would
  184. // not be evaluated, but the whole call gets removed from
  185. // the stack, and in the body of 'set!, the 'val would be
  186. // recursively evaluated, and the 'call/cc would not see
  187. // the variable definition as part of the continuation. So
  188. // what we do istead, is writing 'set! as a macro and have
  189. // the variable definition as a and_then_action, so that
  190. // it is part of the continuation.
  191. profile_with_name("(set!)");
  192. using Globals::Current_Execution;
  193. Lisp_Object* args = Current_Execution.pcs[--Current_Execution.pcs.next_index];
  194. try_void assert_list_length(args, 2);
  195. Lisp_Object* sym = args->value.pair.first;
  196. Lisp_Object* val = args->value.pair.rest->value.pair.first;
  197. try_void assert_type(sym, Lisp_Object_Type::Symbol);
  198. // 2. find the binding and rebind
  199. Current_Execution.cs.append(sym);
  200. Current_Execution.ats.append([] {
  201. using Globals::Current_Execution;
  202. Lisp_Object* val = Current_Execution.cs.data[--Current_Execution.cs.next_index];
  203. Lisp_Object* sym = Current_Execution.cs.data[Current_Execution.cs.next_index-1];
  204. Environment* target_env = find_binding_environment(sym, get_current_environment());
  205. if (!target_env)
  206. target_env = get_root_environment();
  207. define_symbol(sym, val, target_env);
  208. });
  209. (Current_Execution.nass.end()-1)->append(NasAction::And_Then_Action);
  210. // 1. eval the val
  211. Current_Execution.cs.append(val);
  212. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  213. };
  214. define_macro((apply fun fun_args), "TODO") {
  215. // NOTE(Felix): is has to be a macro because apply by
  216. // itself cannot return the result, we have to invoke eval
  217. // and to prevent recursion, apply is a macro
  218. profile_with_name("(apply)");
  219. using Globals::Current_Execution;
  220. Lisp_Object* args = Current_Execution.pcs[--Current_Execution.pcs.next_index];
  221. try_void assert_list_length(args, 2);
  222. Lisp_Object* fun = args->value.pair.first;
  223. Lisp_Object* fun_args = args->value.pair.rest->value.pair.first;
  224. // 3. push args on the stack and apply
  225. Current_Execution.ats.append([] {
  226. // BUG(Felix): we are not pushing on the ams, are we
  227. // doing it wrong?
  228. // Current_Execution.ams.append(Current_Execution.cs.next_index-2);
  229. Lisp_Object* args_as_list = Current_Execution.cs[--Current_Execution.cs.next_index];
  230. for_lisp_list (args_as_list) {
  231. Current_Execution.cs.append(it);
  232. }
  233. Current_Execution.pcs.append(Memory::nil);
  234. (Current_Execution.nass.end()-1)->append(NasAction::Step);
  235. });
  236. (Current_Execution.nass.end()-1)->append(NasAction::And_Then_Action);
  237. // 2. Eval fun_args and keep them on the stack
  238. Current_Execution.ats.append([] {
  239. // NOTE(Felix): Flip the top 2 elements on cs because
  240. // top is now the evaluated function, and below is the unevaluated args
  241. Lisp_Object* tmp = Current_Execution.cs[Current_Execution.cs.next_index-1];
  242. Current_Execution.cs[Current_Execution.cs.next_index-1] = Current_Execution.cs[Current_Execution.cs.next_index-2];
  243. Current_Execution.cs[Current_Execution.cs.next_index-2] = tmp;
  244. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  245. });
  246. (Current_Execution.nass.end()-1)->append(NasAction::And_Then_Action);
  247. // 1. Eval function and keep it on the stack, below it
  248. // store the unevaluated argument list
  249. Current_Execution.ams.append(Current_Execution.cs.next_index);
  250. Current_Execution.cs.append(fun_args);
  251. Current_Execution.cs.append(fun);
  252. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  253. };
  254. define((get-counter),
  255. "When called returns a procedure that represents\n"
  256. "a counter. Each time it is called it returns the\n"
  257. "next whole number.")
  258. {
  259. define_symbol(
  260. Memory::get_symbol("c"),
  261. Memory::create_lisp_object((f64)0));
  262. String file_name_built_ins = Memory::create_string(__FILE__);
  263. define((lambda), "") {
  264. fetch(c);
  265. c->value.number++;
  266. return c;
  267. };
  268. fetch(lambda);
  269. return lambda;
  270. };
  271. define_macro((eval expr),
  272. "Takes one argument, and evaluates it two times.")
  273. {
  274. profile_with_name("(eval)");
  275. using Globals::Current_Execution;
  276. // we know cs.data[cs.next_index] is allocated because the
  277. // macro cal lwas there just before
  278. Current_Execution.cs.data[Current_Execution.cs.next_index++] = Current_Execution.pcs[--Current_Execution.pcs.next_index]->value.pair.first;
  279. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  280. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  281. };
  282. define_macro((begin . rest),
  283. "Takes any number of forms. Evaluates them in order, "
  284. "and returns the last result.")
  285. {
  286. profile_with_name("(begin)");
  287. using Globals::Current_Execution;
  288. Lisp_Object* args = Current_Execution.pcs[--Current_Execution.pcs.next_index];
  289. u32 length = list_length(args);
  290. Current_Execution.cs.reserve(length);
  291. for_lisp_list(args) {
  292. Current_Execution.cs.data[Current_Execution.cs.next_index - 1 + (length - it_index)] = it;
  293. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  294. (Current_Execution.nass.end()-1)->append(NasAction::Pop);
  295. }
  296. --(Current_Execution.nass.end()-1)->next_index;
  297. Current_Execution.cs.next_index += length;
  298. };
  299. define_macro((if test then_part else_part),
  300. "Takes 3 arguments. If the first arguments evaluates to a truthy "
  301. "value, the if expression evaluates the second argument, else "
  302. "it will evaluete the third one and return them respectively.")
  303. {
  304. profile_with_name("(if)");
  305. using Globals::Current_Execution;
  306. /* | | | <test> |
  307. | | -> | <then> |
  308. | <if> | | <else> |
  309. | .... | | ...... | */
  310. Lisp_Object* args = Current_Execution.pcs.data[--Current_Execution.pcs.next_index];
  311. Lisp_Object* test = args->value.pair.first;
  312. args = args->value.pair.rest;
  313. try_void assert_type(args, Lisp_Object_Type::Pair);
  314. Lisp_Object* consequence = args->value.pair.first;
  315. args = args->value.pair.rest;
  316. try_void assert_type(args, Lisp_Object_Type::Pair);
  317. Lisp_Object* alternative = args->value.pair.first;
  318. args = args->value.pair.rest;
  319. try_void assert_type(args, Lisp_Object_Type::Nil);
  320. Current_Execution.cs.append(alternative);
  321. Current_Execution.cs.append(consequence);
  322. Current_Execution.cs.append(test);
  323. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  324. (Current_Execution.nass.end()-1)->append(NasAction::If);
  325. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  326. };
  327. define_macro((define definee . args), "") {
  328. // NOTE(Felix): define has to be a macro, because we need
  329. // to evaluate the value for definee in case it is a
  330. // simple variable (not a function). So ebcause we don't
  331. // want to recursivly evaluate the value, we use a macro
  332. // and a NasAction.
  333. profile_with_name("(define)");
  334. using Globals::Current_Execution;
  335. Lisp_Object* form = Current_Execution.pcs.data[--Current_Execution.pcs.next_index];
  336. Lisp_Object* definee = form->value.pair.first;
  337. form = form->value.pair.rest;
  338. if (definee->type == Lisp_Object_Type::Symbol) {
  339. try_void assert_type(form, Lisp_Object_Type::Pair);
  340. }
  341. Lisp_Object* thing = form->value.pair.first;
  342. Lisp_Object* thing_cons = form;
  343. form = form->value.pair.rest;
  344. Lisp_Object_Type type = definee->type;
  345. switch (type) {
  346. case Lisp_Object_Type::Symbol: {
  347. if (form != Memory::nil) {
  348. Lisp_Object* doc = thing;
  349. try_void assert_type(doc, Lisp_Object_Type::String);
  350. try_void assert_type(form, Lisp_Object_Type::Pair);
  351. thing = form->value.pair.first;
  352. try_void assert("list must end here.", form->value.pair.rest == Memory::nil);
  353. // TODO docs (maybe with hooks) we have to attach
  354. // the docs to the result of evaluating
  355. }
  356. Current_Execution.cs.append(definee);
  357. Current_Execution.cs.append(thing);
  358. (Current_Execution.nass.end()-1)->append(NasAction::Define_Var);
  359. (Current_Execution.nass.end()-1)->append(NasAction::Eval);
  360. } break;
  361. case Lisp_Object_Type::Pair: {
  362. try_void assert_type(definee->value.pair.first, Lisp_Object_Type::Symbol);
  363. Lisp_Object* func;
  364. try_void func = Memory::create_lisp_object_function(Lisp_Function_Type::Lambda);
  365. func->value.function->parent_environment = get_current_environment();
  366. create_arguments_from_lambda_list_and_inject(definee->value.pair.rest, func);
  367. if (thing_cons->type == Lisp_Object_Type::Pair &&
  368. // if there is stuff in the function body
  369. thing_cons->value.pair.first->type == Lisp_Object_Type::String &&
  370. // if the first is a string
  371. thing_cons->value.pair.rest != Memory::nil
  372. // if it is not the last
  373. ) {
  374. // we found docs
  375. Globals::docs.set_object(
  376. func,
  377. Memory::duplicate_string(
  378. thing_cons->value.pair.first->value.string).data);
  379. thing_cons = thing_cons->value.pair.rest;
  380. }
  381. func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons);
  382. define_symbol(definee->value.pair.first, func);
  383. Current_Execution.cs.append(definee->value.pair.first);
  384. } break;
  385. default: {
  386. create_generic_error("you can only define symbols");
  387. return;
  388. }
  389. }
  390. };
  391. define((helper), "") {
  392. profile_with_name("(helper)");
  393. return Memory::create_lisp_object(101.0);
  394. };
  395. define((enable-debug-log), "") {
  396. profile_with_name("(enable-debug-log)");
  397. Globals::debug_log = true;
  398. return Memory::t;
  399. };
  400. define((disable-debug-log), "") {
  401. profile_with_name("(disable-debug-log)");
  402. Globals::debug_log = false;
  403. return Memory::t;
  404. };
  405. define_special((with-debug-log . rest), "") {
  406. profile_with_name("(enable-debug-log)");
  407. fetch(rest);
  408. Lisp_Object* result = Memory::nil;
  409. Globals::debug_log = true;
  410. in_caller_env {
  411. for_lisp_list(rest) {
  412. // TODO(Felix): hooky would be really nice to
  413. // have. Then this would be a macro and we would
  414. // reset the debug log
  415. try result = eval_expr(it);
  416. }
  417. }
  418. Globals::debug_log = false;
  419. return result;
  420. };
  421. define((test (:k (helper))), "") {
  422. profile_with_name("(test)");
  423. fetch(k);
  424. return k;
  425. };
  426. define((= . args),
  427. "Takes 0 or more arguments and returns =t= if all arguments are equal "
  428. "and =()= otherwise.")
  429. {
  430. profile_with_name("(=)");
  431. fetch(args);
  432. if (args == Memory::nil)
  433. return Memory::t;
  434. Lisp_Object* first = args->value.pair.first;
  435. for_lisp_list (args) {
  436. if (!lisp_object_equal(it, first))
  437. return Memory::nil;
  438. }
  439. return Memory::t;
  440. };
  441. define((> . args), "TODO") {
  442. profile_with_name("(>)");
  443. fetch(args);
  444. f64 last_number = strtod("Inf", 0);
  445. for_lisp_list (args) {
  446. try assert_type(it, Lisp_Object_Type::Number);
  447. if (it->value.number >= last_number)
  448. return Memory::nil;
  449. last_number = it->value.number;
  450. }
  451. return Memory::t;
  452. };
  453. define((>= . args), "TODO")
  454. {
  455. profile_with_name("(>=)");
  456. fetch(args);
  457. f64 last_number = strtod("Inf", 0);
  458. for_lisp_list (args) {
  459. try assert_type(it, Lisp_Object_Type::Number);
  460. if (it->value.number > last_number)
  461. return Memory::nil;
  462. last_number = it->value.number;
  463. }
  464. return Memory::t;
  465. };
  466. define((< . args), "TODO")
  467. {
  468. profile_with_name("(<)");
  469. fetch(args);
  470. f64 last_number = strtod("-Inf", 0);
  471. for_lisp_list (args) {
  472. try assert_type(it, Lisp_Object_Type::Number);
  473. if (it->value.number <= last_number)
  474. return Memory::nil;
  475. last_number = it->value.number;
  476. }
  477. return Memory::t;
  478. };
  479. define((<= . args), "TODO")
  480. {
  481. profile_with_name("(<=)");
  482. fetch(args);
  483. f64 last_number = strtod("-Inf", 0);
  484. for_lisp_list (args) {
  485. try assert_type(it, Lisp_Object_Type::Number);
  486. if (it->value.number < last_number)
  487. return Memory::nil;
  488. last_number = it->value.number;
  489. }
  490. return Memory::t;
  491. };
  492. define((+ . args), "TODO")
  493. {
  494. profile_with_name("(+)");
  495. fetch(args);
  496. f64 sum = 0;
  497. for_lisp_list (args) {
  498. try assert_type(it, Lisp_Object_Type::Number);
  499. sum += it->value.number;
  500. }
  501. return Memory::create_lisp_object(sum);
  502. };
  503. define((- . args), "TODO")
  504. {
  505. profile_with_name("(-)");
  506. fetch(args);
  507. if (args == Memory::nil)
  508. return Memory::create_lisp_object(0.0);
  509. try assert_type(args->value.pair.first, Lisp_Object_Type::Number);
  510. f64 difference = args->value.pair.first->value.number;
  511. if (args->value.pair.rest == Memory::nil) {
  512. return Memory::create_lisp_object(-difference);
  513. }
  514. for_lisp_list (args->value.pair.rest) {
  515. try assert_type(it, Lisp_Object_Type::Number);
  516. difference -= it->value.number;
  517. }
  518. return Memory::create_lisp_object(difference);
  519. };
  520. define((* . args), "TODO")
  521. {
  522. profile_with_name("(*)");
  523. fetch(args);
  524. if (args == Memory::nil) {
  525. return Memory::create_lisp_object(1);
  526. }
  527. f64 product = 1;
  528. for_lisp_list (args) {
  529. try assert_type(it, Lisp_Object_Type::Number);
  530. product *= it->value.number;
  531. }
  532. return Memory::create_lisp_object(product);
  533. };
  534. define((/ . args), "TODO")
  535. {
  536. profile_with_name("(/)");
  537. fetch(args);
  538. if (args == Memory::nil) {
  539. return Memory::create_lisp_object(1);
  540. }
  541. try assert_type(args->value.pair.first, Lisp_Object_Type::Number);
  542. f64 quotient = args->value.pair.first->value.number;
  543. for_lisp_list (args->value.pair.rest) {
  544. try assert_type(it, Lisp_Object_Type::Number);
  545. quotient /= it->value.number;
  546. }
  547. return Memory::create_lisp_object(quotient);
  548. };
  549. define((** a b), "TODO") {
  550. profile_with_name("(**)");
  551. fetch(a, b);
  552. try assert_type(a, Lisp_Object_Type::Number);
  553. try assert_type(b, Lisp_Object_Type::Number);
  554. return Memory::create_lisp_object(pow(a->value.number,
  555. b->value.number));
  556. };
  557. define((% a b), "TODO") {
  558. profile_with_name("(%)");
  559. fetch(a, b);
  560. try assert_type(a, Lisp_Object_Type::Number);
  561. try assert_type(b, Lisp_Object_Type::Number);
  562. return Memory::create_lisp_object((s32)a->value.number %
  563. (s32)b->value.number);
  564. };
  565. define((get-random-between a b), "TODO") {
  566. profile_with_name("(get-random-between)");
  567. fetch(a, b);
  568. try assert_type(a, Lisp_Object_Type::Number);
  569. try assert_type(b, Lisp_Object_Type::Number);
  570. f64 fa = a->value.number;
  571. f64 fb = b->value.number;
  572. f64 x = (f64)rand()/(f64)(RAND_MAX);
  573. x *= (fb - fa);
  574. x += fa;
  575. return Memory::create_lisp_object(x);
  576. };
  577. define((gensym), "TODO") {
  578. profile_with_name("(gensym)");
  579. Lisp_Object* node;
  580. try node = Memory::create_lisp_object();
  581. node->type = Lisp_Object_Type::Symbol;
  582. node->value.symbol = Memory::create_string("gensym");
  583. return node;
  584. };
  585. define_special((bound? var), "TODO") {
  586. profile_with_name("(bound?)");
  587. fetch(var);
  588. try assert_type(var, Lisp_Object_Type::Symbol);
  589. Lisp_Object* res;
  590. in_caller_env {
  591. res = try_lookup_symbol(var, get_current_environment());
  592. }
  593. if (res)
  594. return Memory::t;
  595. return Memory::nil;
  596. };
  597. define_special((assert test), "TODO") {
  598. profile_with_name("(assert)");
  599. fetch(test);
  600. // TODO(Felix): it's probably cleaner to have assert be a
  601. // macro + and_then_action to check for error. This is
  602. // also cool so we don't see an anditoinal recursive call
  603. // in the profiler
  604. in_caller_env {
  605. Lisp_Object* res;
  606. try res = eval_expr(test);
  607. if (is_truthy(res))
  608. return Memory::t;
  609. }
  610. char* string = lisp_object_to_string(test, true);
  611. create_generic_error("Userland assertion. (%s)", string);
  612. free(string);
  613. return nullptr;
  614. };
  615. define_special((define-macro form . body), "TODO") {
  616. profile_with_name("(define-macro)");
  617. fetch(form, body);
  618. // TODO(Felix): Macros cannot have docs now
  619. if (form->type != Lisp_Object_Type::Pair) {
  620. create_parsing_error("You can only create function macros.");
  621. return nullptr;
  622. }
  623. Lisp_Object* symbol = form->value.pair.first;
  624. Lisp_Object* lambdalist = form->value.pair.rest;
  625. // creating new lisp object and setting type
  626. Lisp_Object* func;
  627. try func = Memory::create_lisp_object_function(Lisp_Function_Type::Macro);
  628. in_caller_env {
  629. // setting parent env
  630. func->value.function->parent_environment = get_current_environment();
  631. create_arguments_from_lambda_list_and_inject(lambdalist, func);
  632. func->value.function->body.lisp_body = maybe_wrap_body_in_begin(body);
  633. define_symbol(symbol, func);
  634. }
  635. return Memory::nil;
  636. };
  637. define((mutate! target source), "TODO") {
  638. profile_with_name("(mutate!)");
  639. fetch(target, source);
  640. if (target == Memory::nil ||
  641. target == Memory::t ||
  642. target->type == Lisp_Object_Type::Keyword ||
  643. target->type == Lisp_Object_Type::Symbol)
  644. {
  645. create_generic_error("You cannot mutate to nil, t, keywords or symbols because they have to be unique");
  646. }
  647. if (source == Memory::nil ||
  648. source == Memory::t ||
  649. source->type == Lisp_Object_Type::Keyword ||
  650. source->type == Lisp_Object_Type::Symbol)
  651. {
  652. create_generic_error("You cannot mutate nil, t, keywords or symbols");
  653. }
  654. *target = *source;
  655. return target;
  656. };
  657. define((vector-length v), "TODO") {
  658. profile_with_name("(vector-length)");
  659. fetch(v);
  660. try assert_type(v, Lisp_Object_Type::Vector);
  661. return Memory::create_lisp_object((f64)v->value.vector.length);
  662. };
  663. define((vector-ref vec idx), "TODO") {
  664. profile_with_name("(vector-ref)");
  665. fetch(vec, idx);
  666. try assert_type(vec, Lisp_Object_Type::Vector);
  667. try assert_type(idx, Lisp_Object_Type::Number);
  668. s32 int_idx = ((s32)idx->value.number);
  669. try assert("vector access index must be >= 0", int_idx >= 0);
  670. try assert("vector access index must be < length", (u32)int_idx < vec->value.vector.length);
  671. return vec->value.vector.data+int_idx;
  672. };
  673. define((vector-set! vec idx val), "TODO") {
  674. profile_with_name("(vector-set!)");
  675. fetch(vec, idx, val);
  676. try assert_type(vec, Lisp_Object_Type::Vector);
  677. try assert_type(idx, Lisp_Object_Type::Number);
  678. s32 int_idx = ((s32)idx->value.number);
  679. try assert("vector access index must be >= 0", int_idx >= 0);
  680. try assert("vector access index must be < length", (u32)int_idx < vec->value.vector.length);
  681. vec->value.vector.data[int_idx] = *val;
  682. return val;
  683. };
  684. define((set-car! target source), "TODO") {
  685. profile_with_name("(set-car!)");
  686. fetch(target, source);
  687. try assert_type(target, Lisp_Object_Type::Pair);
  688. *target->value.pair.first = *source;
  689. return source;
  690. };
  691. define((set-cdr! target source), "TODO") {
  692. profile_with_name("(set-cdr!)");
  693. fetch(target, source);
  694. try assert_type(target, Lisp_Object_Type::Pair);
  695. *target->value.pair.rest = *source;
  696. return source;
  697. };
  698. define_special((quote datum), "TODO") {
  699. profile_with_name("(quote)");
  700. fetch(datum);
  701. return datum;
  702. };
  703. define_special((quasiquote expr), "TODO") {
  704. profile_with_name("(quasiquote)");
  705. fetch(expr);
  706. Lisp_Object* quasiquote_sym = Memory::get_symbol("quasiquote");
  707. Lisp_Object* unquote_sym = Memory::get_symbol("unquote");
  708. Lisp_Object* unquote_splicing_sym = Memory::get_symbol("unquote-splicing");
  709. // NOTE(Felix): first we have to initialize the variable
  710. // with a garbage lambda, so that we can then overwrite it
  711. // a recursive lambda
  712. const auto unquoteSomeExpressions = [&] (const auto & self, Lisp_Object* expr) -> Lisp_Object* {
  713. // if it is an atom, return it
  714. if (expr->type != Lisp_Object_Type::Pair)
  715. return Memory::copy_lisp_object(expr);
  716. // it is a pair!
  717. Lisp_Object* originalPair = expr->value.pair.first;
  718. // if we find quasiquote, uhu
  719. if (originalPair == quasiquote_sym)
  720. return expr;
  721. if (originalPair == unquote_sym || originalPair == unquote_splicing_sym)
  722. {
  723. // eval replace the stuff
  724. Lisp_Object* ret;
  725. in_caller_env {
  726. try ret = eval_expr(expr->value.pair.rest->value.pair.first);
  727. }
  728. return ret;
  729. }
  730. // it is a list but not starting with the symbol
  731. // unquote, so search in there for stuff to unquote.
  732. // While copying the list
  733. //NOTE(Felix): Of fucking course we have to copy the
  734. // list. The quasiquote will be part of the body of a
  735. // funciton, we can't just modify it because otherwise
  736. // we modify the body of the function and would bake
  737. // in the result...
  738. Lisp_Object* newPair = Memory::nil;
  739. Lisp_Object* newPairHead = newPair;
  740. Lisp_Object* head = expr;
  741. while (head->type == Lisp_Object_Type::Pair) {
  742. // if it is ,@ we have to actually do more work
  743. // and inline the result
  744. if (head->value.pair.first->type == Lisp_Object_Type::Pair &&
  745. head->value.pair.first->value.pair.first == unquote_splicing_sym)
  746. {
  747. Lisp_Object* spliced = self(self, head->value.pair.first);
  748. if (spliced == Memory::nil) {
  749. head = head->value.pair.rest;
  750. continue;
  751. }
  752. try assert_type(spliced, Lisp_Object_Type::Pair);
  753. if (newPair == Memory::nil) {
  754. try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  755. newPairHead = newPair;
  756. } else {
  757. try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  758. newPairHead = newPairHead->value.pair.rest;
  759. newPairHead->value.pair.first = spliced->value.pair.first;
  760. newPairHead->value.pair.rest = spliced->value.pair.rest;
  761. // now skip to the end
  762. while (newPairHead->value.pair.rest != Memory::nil) {
  763. newPairHead = newPairHead->value.pair.rest;
  764. }
  765. }
  766. } else {
  767. if (newPair == Memory::nil) {
  768. try newPair = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  769. newPairHead = newPair;
  770. } else {
  771. try newPairHead->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  772. newPairHead = newPairHead->value.pair.rest;
  773. }
  774. newPairHead->value.pair.first = self(self, head->value.pair.first);
  775. }
  776. // if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair) {
  777. // break;
  778. // }
  779. head = head->value.pair.rest;
  780. }
  781. newPairHead->value.pair.rest = Memory::nil;
  782. return newPair;
  783. };
  784. expr = unquoteSomeExpressions(unquoteSomeExpressions, expr);
  785. return expr;
  786. };
  787. define((not test), "TODO") {
  788. profile_with_name("(not)");
  789. fetch(test);
  790. return is_truthy(test) ? Memory::nil : Memory::t;
  791. };
  792. // // // defun("while", "TODO", __LINE__, cLambda {
  793. // // // try arguments_length = list_length(arguments);
  794. // // // try assert(arguments_length >= 2);
  795. // // // Lisp_Object* condition_part = arguments->value.pair.first;
  796. // // // Lisp_Object* condition;
  797. // // // Lisp_Object* then_part = arguments->value.pair.rest;
  798. // // // Lisp_Object* wrapped_then_part;
  799. // // // try wrapped_then_part = Memory::create_lisp_object_pair(
  800. // // // Memory::get_symbol("begin"),
  801. // // // then_part);
  802. // // // Lisp_Object* result = Memory::nil;
  803. // // // while (true) {
  804. // // // try condition = eval_expr(condition_part);
  805. // // // if (condition == Memory::nil)
  806. // // // break;
  807. // // // try result = eval_expr(wrapped_then_part);
  808. // // // }
  809. // // // return result;
  810. // // // });
  811. define_special((lambda args . body), "TODO") {
  812. profile_with_name("(lambda)");
  813. fetch(args, body);
  814. // creating new lisp object and setting type
  815. Lisp_Object* func;
  816. try func = Memory::create_lisp_object_function(Lisp_Function_Type::Lambda);
  817. in_caller_env {
  818. func->value.function->parent_environment = get_current_environment();
  819. }
  820. try create_arguments_from_lambda_list_and_inject(args, func);
  821. func->value.function->body.lisp_body = maybe_wrap_body_in_begin(body);
  822. return func;
  823. };
  824. define((list . args), "TODO") {
  825. profile_with_name("(list)");
  826. fetch(args);
  827. return args;
  828. };
  829. define((hash-map . args), "TODO") {
  830. profile_with_name("(hash-map)");
  831. fetch(args);
  832. Lisp_Object* ret;
  833. try ret = Memory::create_lisp_object_hash_map();
  834. for_lisp_list (args) {
  835. try assert_type(head->value.pair.rest, Lisp_Object_Type::Pair);
  836. head = head->value.pair.rest;
  837. ret->value.hashMap->set_object(it, head->value.pair.first);
  838. }
  839. return ret;
  840. };
  841. define((hash-map-get hm key), "TODO") {
  842. profile_with_name("(hash-map-get)");
  843. fetch(hm, key);
  844. try assert_type(hm, Lisp_Object_Type::HashMap);
  845. Lisp_Object* ret = (Lisp_Object*)hm->value.hashMap->get_object(key);
  846. if (!ret)
  847. create_symbol_undefined_error("The key was not set in the hashmap");
  848. return ret;
  849. };
  850. define((hash-map-set! hm key value), "TODO") {
  851. profile_with_name("(hash-map-set!)");
  852. fetch(hm, key, value);
  853. try assert_type(hm, Lisp_Object_Type::HashMap);
  854. hm->value.hashMap->set_object(key, value);
  855. return Memory::nil;
  856. };
  857. define((hash-map-delete! hm key), "TODO") {
  858. profile_with_name("(hash-map-delete!)");
  859. fetch(hm, key);
  860. try assert_type(hm, Lisp_Object_Type::HashMap);
  861. hm->value.hashMap->delete_object(key);
  862. return Memory::nil;
  863. };
  864. define((vector . args), "TODO") {
  865. profile_with_name("(vector)");
  866. fetch(args);
  867. Lisp_Object* ret;
  868. u32 length = list_length(args);
  869. try ret = Memory::create_lisp_object_vector(length, args);
  870. return ret;
  871. };
  872. define((cons car cdr), "TODO") {
  873. profile_with_name("(cons)");
  874. fetch(car, cdr);
  875. Lisp_Object* ret;
  876. try ret = Memory::create_lisp_object_pair(car, cdr);
  877. return ret;
  878. };
  879. define((car seq), "TODO") {
  880. profile_with_name("(car)");
  881. fetch(seq);
  882. if (seq == Memory::nil)
  883. return Memory::nil;
  884. try assert_type(seq, Lisp_Object_Type::Pair);
  885. return seq->value.pair.first;
  886. };
  887. define((cdr seq), "TODO") {
  888. profile_with_name("(cdr)");
  889. fetch(seq);
  890. if (seq == Memory::nil)
  891. return Memory::nil;
  892. try assert_type(seq, Lisp_Object_Type::Pair);
  893. return seq->value.pair.rest;
  894. };
  895. define((set-type! node new_type), "TODO") {
  896. profile_with_name("(set-type!)");
  897. fetch(node, new_type);
  898. try assert_type(new_type, Lisp_Object_Type::Keyword);
  899. Globals::user_types.set_object(node, new_type);
  900. return node;
  901. };
  902. define((delete-type! n), "TODO") {
  903. profile_with_name("(delete-type!)");
  904. fetch(n);
  905. Globals::user_types.delete_object(n);
  906. return Memory::t;
  907. };
  908. define((type n), "TODO") {
  909. profile_with_name("(type)");
  910. fetch(n);
  911. if (Globals::user_types.key_exists(n)) {
  912. return (Lisp_Object*)Globals::user_types.get_object(n);
  913. }
  914. Lisp_Object_Type type = n->type;
  915. switch (type) {
  916. case Lisp_Object_Type::Continuation: return Memory::get_keyword("continuation");
  917. case Lisp_Object_Type::Function: {
  918. Function* fun = n->value.function;
  919. if (fun->is_c) {
  920. switch (fun->type.c_function_type) {
  921. case C_Function_Type::cMacro: return Memory::get_keyword("cMacro");
  922. case C_Function_Type::cFunction: return Memory::get_keyword("cFunction");
  923. case C_Function_Type::cSpecial: return Memory::get_keyword("cSpecial");
  924. default: return Memory::get_keyword("c??");
  925. }
  926. } else {
  927. switch (fun->type.lisp_function_type) {
  928. case Lisp_Function_Type::Lambda: return Memory::get_keyword("lambda");
  929. case Lisp_Function_Type::Macro: return Memory::get_keyword("macro");
  930. default: return Memory::get_keyword("??");
  931. }
  932. }
  933. }
  934. case Lisp_Object_Type::HashMap: return Memory::get_keyword("hashmap");
  935. case Lisp_Object_Type::Keyword: return Memory::get_keyword("keyword");
  936. case Lisp_Object_Type::Nil: return Memory::get_keyword("nil");
  937. case Lisp_Object_Type::Number: return Memory::get_keyword("number");
  938. case Lisp_Object_Type::Pair: return Memory::get_keyword("pair");
  939. case Lisp_Object_Type::Pointer: return Memory::get_keyword("pointer");
  940. case Lisp_Object_Type::String: return Memory::get_keyword("string");
  941. case Lisp_Object_Type::Symbol: return Memory::get_keyword("symbol");
  942. case Lisp_Object_Type::T: return Memory::get_keyword("t");
  943. case Lisp_Object_Type::Vector: return Memory::get_keyword("vector");
  944. case(Lisp_Object_Type::Invalid_Garbage_Collected): return Memory::get_keyword("Invalid: Garbage Collected");
  945. case(Lisp_Object_Type::Invalid_Under_Construction): return Memory::get_keyword("Invalid: Under Construction");
  946. }
  947. return Memory::get_keyword("unknown");
  948. };
  949. define_special((info n), "TODO")
  950. {
  951. // NOTE(Felix): we need to define_special because the docstring is
  952. // attached to the symbol. Because some object are singletons
  953. // (symbols, keyowrds, nil, t) we dont want to store docs on the
  954. // object. Otherwise (define k :doc "hallo" :keyword) would modify
  955. // // the global keyword
  956. profile_with_name("(info)");
  957. fetch(n);
  958. print(n);
  959. Lisp_Object* type;
  960. Lisp_Object* val;
  961. in_caller_env {
  962. try type = eval_expr(Memory::create_list(Memory::get_symbol("type"), n));
  963. try val = eval_expr(n);
  964. }
  965. printf(" is of type ");
  966. print(type);
  967. printf(" (internal: %s)", lisp_object_type_to_string(val->type));
  968. printf("\nand is printed as: ");
  969. print(val);
  970. printf("\n\ndocs:\n=====\n %s\n\n",
  971. (Globals::docs.get_object(val))
  972. ? Globals::docs.get_object(val)
  973. : "No docs avaliable");
  974. if (val->type == Lisp_Object_Type::Function)
  975. {
  976. Arguments* args = &val->value.function->args;
  977. printf("Arguments:\n==========\n");
  978. printf("Postitional: {");
  979. if (args->positional.symbols.next_index != 0) {
  980. printf("%s",
  981. Memory::get_c_str(args->positional.symbols.data[0]->value.symbol));
  982. for (u32 i = 1; i < args->positional.symbols.next_index; ++i) {
  983. printf(", %s",
  984. Memory::get_c_str(args->positional.symbols.data[i]->value.symbol));
  985. }
  986. }
  987. printf("}\n");
  988. printf("Keyword: {");
  989. if (args->keyword.values.next_index != 0) {
  990. printf("%s",
  991. Memory::get_c_str(args->keyword.keywords.data[0]->value.symbol));
  992. if (args->keyword.values.data[0]) {
  993. printf(" (");
  994. print(args->keyword.values.data[0], true);
  995. printf(")");
  996. }
  997. for (u32 i = 1; i < args->keyword.values.next_index; ++i) {
  998. printf(", %s",
  999. Memory::get_c_str(args->keyword.keywords.data[i]->value.symbol));
  1000. if (args->keyword.values.data[i]) {
  1001. printf(" (");
  1002. print(args->keyword.values.data[i], true);
  1003. printf(")");
  1004. }
  1005. }
  1006. }
  1007. printf("}\n");
  1008. printf("Rest: {");
  1009. if (args->rest)
  1010. printf("%s",
  1011. Memory::get_c_str(args->rest->value.symbol));
  1012. printf("}\n");
  1013. }
  1014. return Memory::nil;
  1015. };
  1016. define((show n), "TODO") {
  1017. profile_with_name("(show)");
  1018. fetch(n);
  1019. try assert_type(n, Lisp_Object_Type::Function);
  1020. try assert("c-functoins cannot be shown", !n->value.function->is_c);
  1021. puts("body:\n");
  1022. print(n->value.function->body.lisp_body);
  1023. puts("\n");
  1024. printf("parent_env: %p\n",
  1025. n->value.function->parent_environment);
  1026. return Memory::nil;
  1027. };
  1028. define((addr-of var), "TODO") {
  1029. profile_with_name("(addr-of-var)");
  1030. fetch(var);
  1031. return Memory::create_lisp_object(&var);
  1032. };
  1033. define((generate-docs-file file_name), "TODO") {
  1034. profile_with_name("(generate-docs-file)");
  1035. fetch(file_name);
  1036. try assert_type(file_name, Lisp_Object_Type::String);
  1037. in_caller_env {
  1038. try generate_docs(file_name->value.string);
  1039. }
  1040. return Memory::t;
  1041. };
  1042. define((print (:sep " ") (:end "\n") (:repr ()) . things), "TODO") {
  1043. profile_with_name("(print)");
  1044. fetch(sep, end, repr, things);
  1045. if (things != Memory::nil) {
  1046. bool print_repr = (repr != Memory::nil);
  1047. print(things->value.pair.first, print_repr);
  1048. for_lisp_list(things->value.pair.rest) {
  1049. print(sep);
  1050. print(it, print_repr);
  1051. }
  1052. }
  1053. print(end);
  1054. return Memory::nil;
  1055. };
  1056. define((read (:prompt ">")), "TODO") {
  1057. profile_with_name("(read)");
  1058. fetch(prompt);
  1059. print(prompt);
  1060. // TODO(Felix): make read_line return a String*
  1061. char* line = read_line();
  1062. defer {
  1063. free(line);
  1064. };
  1065. String strLine = Memory::create_string(line);
  1066. return Memory::create_lisp_object(strLine);
  1067. };
  1068. define((exit (:code 0)), "TODO") {
  1069. profile_with_name("(exit)");
  1070. fetch(code);
  1071. try assert_type(code, Lisp_Object_Type::Number);
  1072. exit((s32)code->value.number);
  1073. };
  1074. define((show-environment), "TODO") {
  1075. profile_with_name("(show-environment)");
  1076. in_caller_env {
  1077. print_environment(get_current_environment());
  1078. }
  1079. return Memory::nil;
  1080. };
  1081. define((memstat), "TODO") {
  1082. profile_with_name("(memstat)");
  1083. Memory::print_status();
  1084. return Memory::nil;
  1085. };
  1086. define_special((attempt try_part catch_part), "TODO") {
  1087. profile_with_name("(attempt)");
  1088. fetch(try_part, catch_part);
  1089. Lisp_Object* result;
  1090. in_caller_env {
  1091. ignore_logging {
  1092. dont_break_on_errors {
  1093. result = eval_expr(try_part);
  1094. if (Globals::error) {
  1095. delete_error();
  1096. try result = eval_expr(catch_part);
  1097. }
  1098. }
  1099. }
  1100. }
  1101. return result;
  1102. };
  1103. define((load file), "TODO") {
  1104. profile_with_name("(load)");
  1105. fetch(file);
  1106. try assert_type(file, Lisp_Object_Type::String);
  1107. Lisp_Object* result;
  1108. in_caller_env {
  1109. try result = built_in_load(file->value.string);
  1110. }
  1111. return result;
  1112. };
  1113. define((import f), "TODO") {
  1114. profile_with_name("(import)");
  1115. fetch(f);
  1116. try assert_type(f, Lisp_Object_Type::String);
  1117. Lisp_Object *result;
  1118. in_caller_env {
  1119. try result = built_in_import(f->value.string);
  1120. }
  1121. return Memory::t;
  1122. };
  1123. define((copy obj), "TODO") {
  1124. profile_with_name("(copy)");
  1125. fetch(obj);
  1126. return Memory::copy_lisp_object(obj);
  1127. };
  1128. define((error type message), "TODO") {
  1129. profile_with_name("(error)");
  1130. fetch(type, message);
  1131. // TODO(Felix): make the error function useful
  1132. try assert_type(type, Lisp_Object_Type::Keyword);
  1133. try assert_type(message, Lisp_Object_Type::String);
  1134. using Globals::error;
  1135. error = new(Error);
  1136. error->type = type;
  1137. error->message = message->value.string;
  1138. create_generic_error("Userlanderror");
  1139. return nullptr;
  1140. };
  1141. define((symbol->keyword sym), "TODO") {
  1142. profile_with_name("(symbol->keyword)");
  1143. fetch(sym);
  1144. try assert_type(sym, Lisp_Object_Type::Symbol);
  1145. return Memory::get_keyword(sym->value.symbol);
  1146. };
  1147. define((symbol->string sym), "TODO") {
  1148. profile_with_name("(symbol->string)");
  1149. fetch(sym);
  1150. try assert_type(sym, Lisp_Object_Type::Symbol);
  1151. return Memory::create_lisp_object(
  1152. Memory::duplicate_string(sym->value.symbol));
  1153. };
  1154. define((string->symbol str), "TODO") {
  1155. profile_with_name("(string->symbol)");
  1156. fetch(str);
  1157. // TODO(Felix): do some sanity checks on the string. For
  1158. // example, numbers are not valid symbols.
  1159. try assert_type(str, Lisp_Object_Type::String);
  1160. return Memory::get_symbol(Memory::duplicate_string(str->value.string));
  1161. };
  1162. define((concat-strings . strings), "TODO") {
  1163. profile_with_name("(concat-strings)");
  1164. fetch(strings);
  1165. u32 resulting_string_len = 0;
  1166. for_lisp_list (strings) {
  1167. try assert_type(it, Lisp_Object_Type::String);
  1168. resulting_string_len += it->value.string.length;
  1169. }
  1170. String resulting_string = Memory::create_string("", resulting_string_len);
  1171. u32 index_in_string = 0;
  1172. for_lisp_list (strings) {
  1173. strcpy(resulting_string.data+index_in_string,
  1174. Memory::get_c_str(it->value.string));
  1175. index_in_string += it->value.string.length;
  1176. }
  1177. return Memory::create_lisp_object(resulting_string);
  1178. };
  1179. return nullptr;
  1180. }
  1181. }