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.
 
 
 
 
 
 

563 lines
22 KiB

  1. proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> Lisp_Object* {
  2. Environment* new_env;
  3. try new_env = Memory::create_child_environment(function->parent_environment);
  4. push_environment(new_env);
  5. defer {
  6. pop_environment();
  7. };
  8. Lisp_Object* sym, *val; // used as temp storage to use `try`
  9. String_Array_List* read_in_keywords;
  10. int obligatory_keywords_count = 0;
  11. int read_obligatory_keywords_count = 0;
  12. proc read_positional_args = [&]() -> void {
  13. for (int i = 0; i < function->positional_arguments->next_index; ++i) {
  14. if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) {
  15. create_wrong_number_of_arguments_error(function->positional_arguments->next_index, i);
  16. return;
  17. }
  18. // TODO(Felix): here we create new lisp_object_symbols from
  19. // their identifiers but before we converted them to
  20. // strings from symbols... Wo maybe just use the symbols?
  21. // NOTE(Felix): We have to copy all the arguments, otherwise
  22. // we change the program code.
  23. try_void sym = function->positional_arguments->symbols[i];
  24. define_symbol(
  25. sym,
  26. Memory::copy_lisp_object_except_pairs(arguments->value.pair.first));
  27. arguments = arguments->value.pair.rest;
  28. }
  29. };
  30. proc read_keyword_args = [&]() -> void {
  31. // keyword arguments: use all given ones and keep track of the
  32. // added ones (array list), if end of parameters in encountered or
  33. // something that is not a keyword is encountered or a keyword
  34. // that is not recognized is encoutered, jump out of the loop.
  35. read_in_keywords = create_String_array_list();
  36. if (arguments == Memory::nil)
  37. return;
  38. // find out how many keyword args we /have/ to read
  39. for (int i = 0; i < function->keyword_arguments->next_index; ++i) {
  40. if (function->keyword_arguments->values->data[i] == nullptr)
  41. ++obligatory_keywords_count;
  42. else
  43. break;
  44. }
  45. while (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) {
  46. // check if this one is even an accepted keyword
  47. bool accepted = false;
  48. for (int i = 0; i < function->keyword_arguments->next_index; ++i) {
  49. if (string_equal(
  50. arguments->value.pair.first->value.symbol.identifier,
  51. function->keyword_arguments->keywords[i]->value.symbol.identifier))
  52. {
  53. accepted = true;
  54. break;
  55. }
  56. }
  57. if (!accepted) {
  58. // NOTE(Felix): if we are actually done with all the
  59. // necessary keywords then we have to count the rest
  60. // as :rest here, instead od always creating an error
  61. // (special case with default variables)
  62. if (read_obligatory_keywords_count == obligatory_keywords_count)
  63. return;
  64. create_generic_error(
  65. "The function does not take the keyword argument ':%s'\n"
  66. "and not all required keyword arguments have been read\n"
  67. "in to potentially count it as the rest argument.",
  68. &(arguments->value.pair.first->value.symbol.identifier->data));
  69. return;
  70. }
  71. // check if it was already read in
  72. for (int i = 0; i < read_in_keywords->next_index; ++i) {
  73. if (string_equal(
  74. arguments->value.pair.first->value.symbol.identifier,
  75. read_in_keywords->data[i]))
  76. {
  77. // NOTE(Felix): if we are actually done with all the
  78. // necessary keywords then we have to count the rest
  79. // as :rest here, instead od always creating an error
  80. // (special case with default variables)
  81. if (read_obligatory_keywords_count == obligatory_keywords_count)
  82. return;
  83. create_generic_error(
  84. "The function already read the keyword argument ':%s'",
  85. &(arguments->value.pair.first->value.symbol.identifier->data));
  86. return;
  87. }
  88. }
  89. // okay so we found a keyword that has to be read in and was
  90. // not already read in, is there a next element to actually
  91. // set it to?
  92. if (Memory::get_type(arguments->value.pair.rest) != Lisp_Object_Type::Pair) {
  93. create_generic_error(
  94. "Attempting to set the keyword argument ':%s', but no value was supplied.",
  95. &(arguments->value.pair.first->value.symbol.identifier->data));
  96. return;
  97. }
  98. // if not set it and then add it to the array list
  99. try_void sym = Memory::get_or_create_lisp_object_symbol(arguments->value.pair.first->value.symbol.identifier);
  100. // NOTE(Felix): It seems we do not need to evaluate the argument here...
  101. try_void define_symbol(
  102. sym,
  103. Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first));
  104. append_to_array_list(read_in_keywords, arguments->value.pair.first->value.symbol.identifier);
  105. ++read_obligatory_keywords_count;
  106. // overstep both for next one
  107. arguments = arguments->value.pair.rest->value.pair.rest;
  108. if (arguments == Memory::nil) {
  109. break;
  110. }
  111. }
  112. };
  113. proc check_keyword_args = [&]() -> void {
  114. // check if all necessary keywords have been read in
  115. for (int i = 0; i < function->keyword_arguments->next_index; ++i) {
  116. String* defined_keyword = function->keyword_arguments->keywords[i]->value.symbol.identifier;
  117. bool was_set = false;
  118. for (int j = 0; j < read_in_keywords->next_index; ++j) {
  119. if (string_equal(
  120. read_in_keywords->data[j],
  121. defined_keyword))
  122. {
  123. was_set = true;
  124. break;
  125. }
  126. }
  127. if (function->keyword_arguments->values->data[i] == nullptr) {
  128. // if this one does not have a default value
  129. if (!was_set) {
  130. create_generic_error(
  131. "There was no value supplied for the required "
  132. "keyword argument ':%s'.",
  133. &defined_keyword->data);
  134. return;
  135. }
  136. } else {
  137. // this one does have a default value, lets see if we have
  138. // to use it or if the user supplied his own
  139. if (!was_set) {
  140. try_void sym = Memory::get_or_create_lisp_object_symbol(defined_keyword);
  141. try_void val = Memory::copy_lisp_object_except_pairs(function->keyword_arguments->values->data[i]);
  142. define_symbol(sym, val);
  143. }
  144. }
  145. }
  146. };
  147. proc read_rest_arg = [&]() -> void {
  148. if (arguments == Memory::nil) {
  149. if (function->rest_argument) {
  150. try_void sym = Memory::get_or_create_lisp_object_symbol(function->rest_argument);
  151. define_symbol(sym, Memory::nil);
  152. }
  153. } else {
  154. if (function->rest_argument) {
  155. try_void sym = Memory::get_or_create_lisp_object_symbol(function->rest_argument);
  156. define_symbol(
  157. sym,
  158. // NOTE(Felix): arguments will be a list, and I THINK
  159. // we do not need to copy it...
  160. arguments);
  161. } else {
  162. // rest was not declared but additional arguments were found
  163. create_generic_error(
  164. "A rest argument was not declared "
  165. "but the function was called with additional arguments.");
  166. return;
  167. }
  168. }
  169. };
  170. try read_positional_args();
  171. try read_keyword_args();
  172. try check_keyword_args();
  173. try read_rest_arg();
  174. Lisp_Object* result;
  175. try result = eval_expr(function->body);
  176. return result;
  177. }
  178. /**
  179. This parses the argument specification of funcitons into their
  180. Function struct. It does this by allocating new
  181. positional_arguments, keyword_arguments and rest_argument and
  182. filling it in
  183. */
  184. proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
  185. // first init the fields
  186. function->positional_arguments = create_positional_argument_list(16);
  187. function->keyword_arguments = create_keyword_argument_list(16);
  188. function->rest_argument = nullptr;
  189. // okay let's try to read some positional arguments
  190. while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) {
  191. if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) {
  192. if (string_equal(arguments->value.pair.first->value.symbol.identifier, "keys") ||
  193. string_equal(arguments->value.pair.first->value.symbol.identifier, "rest"))
  194. break;
  195. else {
  196. create_parsing_error("A non recognized marker was found "
  197. "in the lambda list: ':%s'",
  198. &arguments->value.pair.first->value.symbol.identifier->data);
  199. return;
  200. }
  201. }
  202. if (Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) {
  203. create_parsing_error("Only symbols and keywords can be "
  204. "parsed here, but found '%s'",
  205. Lisp_Object_Type_to_string(Memory::get_type(arguments->value.pair.first)));
  206. return;
  207. }
  208. // okay wow we found an actual symbol
  209. append_to_positional_argument_list(
  210. function->positional_arguments,
  211. arguments->value.pair.first);
  212. arguments = arguments->value.pair.rest;
  213. }
  214. // okay we are done with positional arguments, lets check for
  215. // keywords,
  216. if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) {
  217. if (arguments != Memory::nil)
  218. create_parsing_error("The lambda list must be nil terminated.");
  219. return;
  220. }
  221. if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword &&
  222. string_equal(arguments->value.pair.first->value.symbol.identifier, "keys"))
  223. {
  224. arguments = arguments->value.pair.rest;
  225. if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) {
  226. create_parsing_error("Actual keys have to follow the :keys indicator.");
  227. }
  228. // if (arguments->value.pair.first->type != Lisp_Object_Type::Symbol) {
  229. // create_parsing_error(
  230. // "Only symbols can be parsed here, but found '%s'.",
  231. // Lisp_Object_Type_to_string(arguments->value.pair.first->type));
  232. // return;
  233. // }
  234. while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) {
  235. if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) {
  236. if (string_equal(arguments->value.pair.first->value.symbol.identifier, "rest"))
  237. break;
  238. else {
  239. create_parsing_error(
  240. "Only the :rest keyword can be parsed here, but got ':%s'.",
  241. &arguments->value.pair.first->value.symbol.identifier->data);
  242. return;
  243. }
  244. }
  245. if (Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol) {
  246. create_parsing_error(
  247. "Only symbols can be parsed here, but found '%s'.",
  248. Lisp_Object_Type_to_string(Memory::get_type(arguments->value.pair.first)));
  249. return;
  250. }
  251. // we found a symbol (arguments->value.pair->first) for
  252. // the keyword args! Let's check if the next arguement is
  253. // :defaults-to
  254. Lisp_Object* next = arguments->value.pair.rest;
  255. if (Memory::get_type(next) == Lisp_Object_Type::Pair &&
  256. Memory::get_type(next->value.pair.first) == Lisp_Object_Type::Keyword &&
  257. string_equal(next->value.pair.first->value.symbol.identifier,
  258. "defaults-to"))
  259. {
  260. // check if there is a next argument too, otherwise it
  261. // would be an error
  262. next = next->value.pair.rest;
  263. if (Memory::get_type(next) == Lisp_Object_Type::Pair) {
  264. Lisp_Object* ret;
  265. push_environment(function->parent_environment);
  266. defer {
  267. pop_environment();
  268. };
  269. try_void ret = eval_expr(next->value.pair.first);
  270. append_to_keyword_argument_list(function->keyword_arguments,
  271. arguments->value.pair.first,
  272. ret);
  273. arguments = next->value.pair.rest;
  274. } else {
  275. create_parsing_error("Expecting a value after 'defaults-to'");
  276. return;
  277. }
  278. } else {
  279. // No :defaults-to, so just add it to the list
  280. append_to_keyword_argument_list(function->keyword_arguments,
  281. arguments->value.pair.first,
  282. nullptr);
  283. arguments = next;
  284. }
  285. }
  286. }
  287. // Now we are also done with keyword arguments, lets check for
  288. // if there is a rest argument
  289. if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) {
  290. if (arguments != Memory::nil)
  291. create_parsing_error("The lambda list must be nil terminated.");
  292. return;
  293. }
  294. if (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword &&
  295. string_equal(arguments->value.pair.first->value.symbol.identifier, "rest"))
  296. {
  297. arguments = arguments->value.pair.rest;
  298. if (// arguments->type != Lisp_Object_Type::Pair ||
  299. Memory::get_type(arguments->value.pair.first) != Lisp_Object_Type::Symbol)
  300. {
  301. create_parsing_error("After the 'rest' marker there must follow a symbol.");
  302. return;
  303. }
  304. function->rest_argument = arguments->value.pair.first->value.symbol.identifier;
  305. if (arguments->value.pair.rest != Memory::nil) {
  306. create_parsing_error("The lambda list must end after the rest symbol");
  307. }
  308. } else {
  309. printf("this should not happen?");
  310. create_generic_error("What is happening?");
  311. }
  312. }
  313. proc list_length(Lisp_Object* node) -> int {
  314. if (node == Memory::nil)
  315. return 0;
  316. assert_type(node, Lisp_Object_Type::Pair);
  317. int len = 0;
  318. while (Memory::get_type(node) == Lisp_Object_Type::Pair) {
  319. ++len;
  320. node = node->value.pair.rest;
  321. if (node == Memory::nil)
  322. return len;
  323. }
  324. create_parsing_error("Can't calculate length of ill formed list.");
  325. return 0;
  326. }
  327. proc extract_keyword_value(char* keyword, Parsed_Arguments* args) -> Lisp_Object* {
  328. // NOTE(Felix): This will be a hashmap lookup later
  329. for (int i = 0; i < args->keyword_keys->next_index; ++i) {
  330. if (string_equal(args->keyword_keys->data[i]->value.symbol.identifier, keyword))
  331. return args->keyword_values->data[i];
  332. }
  333. return nullptr;
  334. }
  335. proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_Object* {
  336. int my_out_arguments_length = 0;
  337. if (arguments == Memory::nil) {
  338. *(out_arguments_length) = 0;
  339. return arguments;
  340. }
  341. Lisp_Object* evaluated_arguments;
  342. try evaluated_arguments = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  343. Lisp_Object* evaluated_arguments_head = evaluated_arguments;
  344. Lisp_Object* current_head = arguments;
  345. while (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
  346. try evaluated_arguments_head->value.pair.first = eval_expr(current_head->value.pair.first);
  347. evaluated_arguments_head->value.pair.first->sourceCodeLocation = current_head->value.pair.first->sourceCodeLocation;
  348. current_head = current_head->value.pair.rest;
  349. if (Memory::get_type(current_head) == Lisp_Object_Type::Pair) {
  350. try evaluated_arguments_head->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
  351. evaluated_arguments_head = evaluated_arguments_head->value.pair.rest;
  352. } else if (current_head == Memory::nil) {
  353. evaluated_arguments_head->value.pair.rest = current_head;
  354. } else {
  355. create_parsing_error("Attempting to evaluate ill formed argument list.");
  356. return nullptr;
  357. }
  358. ++my_out_arguments_length;
  359. }
  360. *(out_arguments_length) = my_out_arguments_length;
  361. return evaluated_arguments;
  362. }
  363. proc eval_expr(Lisp_Object* node) -> Lisp_Object* {
  364. using namespace Globals::Current_Execution;
  365. append_to_array_list(call_stack, node);
  366. defer {
  367. // NOTE(Felix): We only delete the current entry from the call
  368. // stack, if we did not encounter an error, otherwise we neet
  369. // to preserve the callstack to print it later. it will be
  370. // cleared in log_error().
  371. if (!Globals::error)
  372. --call_stack->next_index;
  373. };
  374. switch (Memory::get_type(node)) {
  375. case Lisp_Object_Type::T:
  376. case Lisp_Object_Type::Nil:
  377. case Lisp_Object_Type::Number:
  378. case Lisp_Object_Type::Keyword:
  379. case Lisp_Object_Type::String:
  380. case Lisp_Object_Type::Function:
  381. case Lisp_Object_Type::CFunction:
  382. return node;
  383. case Lisp_Object_Type::Symbol: {
  384. Lisp_Object* value;
  385. try value = lookup_symbol(node, get_current_environment());
  386. return value;
  387. }
  388. case Lisp_Object_Type::Pair: {
  389. Lisp_Object* lispOperator;
  390. if (Memory::get_type(node->value.pair.first) != Lisp_Object_Type::CFunction &&
  391. Memory::get_type(node->value.pair.first) != Lisp_Object_Type::Function)
  392. {
  393. try lispOperator = eval_expr(node->value.pair.first);
  394. } else {
  395. lispOperator = node->value.pair.first;
  396. }
  397. Lisp_Object* arguments = node->value.pair.rest;
  398. int arguments_length;
  399. // check for c function
  400. if (Memory::get_type(lispOperator) == Lisp_Object_Type::CFunction) {
  401. Lisp_Object* result;
  402. try result = lispOperator->value.cFunction->function(arguments);
  403. return result;
  404. }
  405. // check for lisp function
  406. if (Memory::get_type(lispOperator) == Lisp_Object_Type::Function) {
  407. // only for lambdas we evaluate the arguments before
  408. // apllying, for the other types, special-lambda and macro
  409. // we do not need.
  410. if (lispOperator->value.function.type == Function_Type::Lambda) {
  411. try arguments = eval_arguments(arguments, &arguments_length);
  412. }
  413. Lisp_Object* result;
  414. try result = apply_arguments_to_function(arguments, &lispOperator->value.function);
  415. // NOTE(Felix): The parser does not understnad (import ..)
  416. // so it cannot expand imported macros at read time
  417. // (because at read time, they are not imported yet, this
  418. // is done at runtime...). That is why we sometimes have
  419. // stray macros fying around, in that case, we expand them
  420. // and bake them in, so they do not have to be expanded
  421. // later again. We will call this "lazy macro expansion"
  422. if (lispOperator->value.function.type == Function_Type::Macro) {
  423. *node = *result;
  424. try result = eval_expr(result);
  425. }
  426. return result;
  427. }
  428. }
  429. default: {
  430. create_generic_error("%s is not a function.", Lisp_Object_Type_to_string(Memory::get_type(node)));
  431. return nullptr;
  432. }
  433. }
  434. }
  435. proc is_truthy(Lisp_Object* expression) -> bool {
  436. Lisp_Object* result;
  437. try result = eval_expr(expression);
  438. return result != Memory::nil;
  439. }
  440. proc interprete_file (char* file_name) -> Lisp_Object* {
  441. Memory::init(4096 * 256, 1024, 4096 * 256);
  442. Environment* root_env = get_root_environment();
  443. Environment* user_env;
  444. try user_env = Memory::create_child_environment(root_env);
  445. push_environment(user_env);
  446. defer {
  447. pop_environment();
  448. };
  449. Lisp_Object* result = built_in_load(Memory::create_string(file_name));
  450. if (Globals::error) {
  451. log_error();
  452. delete_error();
  453. return nullptr;
  454. }
  455. return result;
  456. }
  457. proc interprete_stdin() -> void {
  458. Memory::init(4096 * 256, 1024, 4096 * 256);
  459. Environment* root_env = get_root_environment();
  460. Environment* user_env = Memory::create_child_environment(root_env);
  461. push_environment(user_env);
  462. defer {
  463. pop_environment();
  464. };
  465. if (Globals::error) {
  466. log_error();
  467. delete_error();
  468. return;
  469. }
  470. Parser::environment_for_macros = user_env;
  471. printf("Welcome to the lispy interpreter.\n");
  472. char* line;
  473. Lisp_Object* parsed, * evaluated;
  474. while (true) {
  475. printf("> ");
  476. line = read_expression();
  477. defer {
  478. free(line);
  479. };
  480. parsed = Parser::parse_single_expression(line);
  481. if (Globals::error) {
  482. log_error();
  483. delete_error();
  484. continue;
  485. }
  486. evaluated = eval_expr(parsed);
  487. if (Globals::error) {
  488. log_error();
  489. delete_error();
  490. continue;
  491. }
  492. if (evaluated != Memory::nil) {
  493. print(evaluated);
  494. printf("\n");
  495. }
  496. }
  497. }