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

497 строки
18 KiB

  1. proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> Lisp_Object* {
  2. Environment* new_env = Memory::create_child_environment(function->parent_environment);
  3. // positional arguments
  4. for (int i = 0; i < function->positional_arguments->next_index; ++i) {
  5. if (arguments->type == Lisp_Object_Type::Pair) {
  6. // TODO(Felix): here we create new lisp_object_symbols from
  7. // their identifiers but before we converted them to
  8. // strings from symbols... Wo maybe just use the symbols?
  9. define_symbol(
  10. Memory::create_lisp_object_symbol(function->positional_arguments->identifiers[i]),
  11. arguments->value.pair->first, new_env);
  12. } else {
  13. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  14. return nullptr;
  15. }
  16. arguments = arguments->value.pair->rest;
  17. }
  18. String_Array_List* read_in_keywords = create_String_array_list(16);
  19. if (arguments->type == Lisp_Object_Type::Nil)
  20. goto checks;
  21. // keyword arguments: use all given ones and keep track of the
  22. // added ones (array list), if end of parameters in encountered or
  23. // something that is not a keyword is encountered or a keyword
  24. // that is not recognized is encoutered, jump out of the loop.
  25. while (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) {
  26. // check if this one is even an accepted keyword
  27. bool accepted = false;
  28. for (int i = 0; i < function->keyword_arguments->next_index; ++i) {
  29. if (string_equal(
  30. arguments->value.pair->first->value.keyword->identifier,
  31. function->keyword_arguments->identifiers[i]))
  32. {
  33. accepted = true;
  34. break;
  35. }
  36. }
  37. if (!accepted) {
  38. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  39. return nullptr;
  40. }
  41. // check if it was already read in
  42. for (int i = 0; i < read_in_keywords->next_index; ++i) {
  43. if (string_equal(
  44. arguments->value.pair->first->value.keyword->identifier,
  45. read_in_keywords->data[i]))
  46. {
  47. // TODO(Felix): if we are actually done with all the
  48. // necessary keywords then we have to count the rest
  49. // as :rest here, instead od always creating an error
  50. // (special case with default variables)
  51. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  52. return nullptr;
  53. }
  54. }
  55. // okay so we found a keyword that has to be read in and was
  56. // not already read in, is there a next element to actually
  57. // set it to?
  58. if (arguments->value.pair->rest->type != Lisp_Object_Type::Pair) {
  59. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  60. return nullptr;
  61. }
  62. // if not set it and then add it to the array list
  63. define_symbol(
  64. Memory::create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier),
  65. arguments->value.pair->rest->value.pair->first,
  66. new_env);
  67. append_to_String_array_list(read_in_keywords, arguments->value.pair->first->value.keyword->identifier);
  68. // overstep both for next one
  69. arguments = arguments->value.pair->rest->value.pair->rest;
  70. if (arguments->type == Lisp_Object_Type::Nil) {
  71. break;
  72. }
  73. }
  74. checks:
  75. // check if all necessary keywords have been read in
  76. for (int i = 0; i < function->keyword_arguments->next_index; ++i) {
  77. char* defined_keyword = function->keyword_arguments->identifiers[i];
  78. bool was_set = false;
  79. for (int j = 0; j < read_in_keywords->next_index; ++j) {
  80. if (string_equal(
  81. read_in_keywords->data[j],
  82. defined_keyword))
  83. {
  84. was_set = true;
  85. break;
  86. }
  87. }
  88. if (function->keyword_arguments->values->data[i] == nullptr) {
  89. // if this one does not have a default value
  90. if (!was_set) {
  91. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  92. return nullptr;
  93. }
  94. } else {
  95. // this one does have a default value, lets see if we have
  96. // to use it or if the user supplied his own
  97. if (!was_set) {
  98. define_symbol(
  99. Memory::create_lisp_object_symbol(defined_keyword),
  100. Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env);
  101. }
  102. }
  103. }
  104. if (arguments->type == Lisp_Object_Type::Nil) {
  105. if (function->rest_argument) {
  106. define_symbol(
  107. Memory::create_lisp_object_symbol(function->rest_argument),
  108. Memory::create_lisp_object_nil(), new_env);
  109. }
  110. } else {
  111. if (function->rest_argument) {
  112. define_symbol(
  113. Memory::create_lisp_object_symbol(function->rest_argument),
  114. arguments, new_env);
  115. } else {
  116. // rest was not declared but additional arguments were found
  117. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  118. return nullptr;
  119. }
  120. }
  121. Lisp_Object* result;
  122. try {
  123. result = eval_expr(function->body, new_env);
  124. }
  125. return result;
  126. }
  127. /*
  128. (prog
  129. (define type--before type)
  130. (define type
  131. (lambda (e)
  132. (if (and (= (type--before e) :pair) (= (first e) :my-type))
  133. :my-type
  134. (type--before e))))
  135. )
  136. */
  137. /**
  138. This parses the argument specification of funcitons into their
  139. Function struct. It dois this by allocating new
  140. positional_arguments, keyword_arguments and rest_argument and
  141. filling it in
  142. */
  143. proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void {
  144. // first init the fields
  145. function->positional_arguments = create_positional_argument_list(16);
  146. function->keyword_arguments = create_keyword_argument_list(16);
  147. function->rest_argument = nullptr;
  148. // okay let's try to read some positional arguments
  149. while (arguments->type == Lisp_Object_Type::Pair) {
  150. if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) {
  151. if (string_equal(arguments->value.pair->first->value.keyword->identifier, "keys") ||
  152. string_equal(arguments->value.pair->first->value.keyword->identifier, "rest"))
  153. break;
  154. else {
  155. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  156. return;
  157. }
  158. }
  159. if (arguments->value.pair->first->type != Lisp_Object_Type::Symbol) {
  160. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  161. return;
  162. }
  163. // okay wow we found an actual symbol
  164. append_to_positional_argument_list(
  165. function->positional_arguments,
  166. arguments->value.pair->first->value.symbol->identifier);
  167. arguments = arguments->value.pair->rest;
  168. }
  169. // okay we are done with positional arguments, lets check for
  170. // keywords,
  171. if (arguments->type != Lisp_Object_Type::Pair) {
  172. if (arguments->type != Lisp_Object_Type::Nil)
  173. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  174. return;
  175. }
  176. if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword &&
  177. string_equal(arguments->value.pair->first->value.keyword->identifier, "keys"))
  178. {
  179. arguments = arguments->value.pair->rest;
  180. if (arguments->type != Lisp_Object_Type::Pair ||
  181. arguments->value.pair->first->type != Lisp_Object_Type::Symbol)
  182. {
  183. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  184. return;
  185. }
  186. while (arguments->type == Lisp_Object_Type::Pair) {
  187. if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) {
  188. if (string_equal(arguments->value.pair->first->value.keyword->identifier, "rest"))
  189. break;
  190. else {
  191. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  192. return;
  193. }
  194. }
  195. if (arguments->value.pair->first->type != Lisp_Object_Type::Symbol) {
  196. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  197. return;
  198. }
  199. // we found a symbol (arguments->value.pair->first) for
  200. // the keyword args! Let's check if the next arguement is
  201. // :defaults-to
  202. Lisp_Object* next = arguments->value.pair->rest;
  203. if (next->type == Lisp_Object_Type::Pair &&
  204. next->value.pair->first->type == Lisp_Object_Type::Keyword &&
  205. string_equal(next->value.pair->first->value.keyword->identifier,
  206. "defaults-to"))
  207. {
  208. // check if there is a next argument too, otherwise it
  209. // would be an error
  210. next = next->value.pair->rest;
  211. if (next->type == Lisp_Object_Type::Pair) {
  212. append_to_keyword_argument_list(function->keyword_arguments,
  213. arguments->value.pair->first->value.symbol->identifier,
  214. next->value.pair->first);
  215. arguments = next->value.pair->rest;
  216. } else {
  217. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  218. return;
  219. }
  220. } else {
  221. // No :defaults-to, so just add it to the list
  222. append_to_keyword_argument_list(function->keyword_arguments,
  223. arguments->value.pair->first->value.symbol->identifier,
  224. nullptr);
  225. arguments = next;
  226. }
  227. }
  228. }
  229. // Now we are also done with keyword arguments, lets check for
  230. // if there is a rest argument
  231. if (arguments->type != Lisp_Object_Type::Pair) {
  232. if (arguments->type != Lisp_Object_Type::Nil)
  233. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  234. return;
  235. }
  236. if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword &&
  237. string_equal(arguments->value.pair->first->value.keyword->identifier, "rest"))
  238. {
  239. arguments = arguments->value.pair->rest;
  240. if (arguments->type != Lisp_Object_Type::Pair ||
  241. arguments->value.pair->first->type != Lisp_Object_Type::Symbol)
  242. {
  243. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  244. return;
  245. }
  246. function->rest_argument = arguments->value.pair->first->value.symbol->identifier;
  247. if (arguments->value.pair->rest->type != Lisp_Object_Type::Nil) {
  248. create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation);
  249. }
  250. } else {
  251. printf("this should not happen?");
  252. create_error(Error_Type::Unknown_Error, arguments->sourceCodeLocation);
  253. }
  254. }
  255. proc list_length(Lisp_Object* node) -> int {
  256. if (node->type == Lisp_Object_Type::Nil)
  257. return 0;
  258. if (node->type != Lisp_Object_Type::Pair) {
  259. create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation);
  260. return 0;
  261. }
  262. int len = 0;
  263. while (node->type == Lisp_Object_Type::Pair) {
  264. ++len;
  265. node = node->value.pair->rest;
  266. if (node->type == Lisp_Object_Type::Nil)
  267. return len;
  268. }
  269. create_error(Error_Type::Ill_Formed_List, node->sourceCodeLocation);
  270. return 0;
  271. }
  272. proc extract_keyword_value(char* keyword, Parsed_Arguments* args) -> Lisp_Object* {
  273. // NOTE(Felix): This will be a hashmap lookup later
  274. for (int i = 0; i < args->keyword_keys->next_index; ++i) {
  275. if (string_equal(args->keyword_keys->data[i]->value.keyword->identifier, keyword))
  276. return args->keyword_values->data[i];
  277. }
  278. return nullptr;
  279. }
  280. proc eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length) -> Lisp_Object* {
  281. int my_out_arguments_length = 0;
  282. if (arguments->type == Lisp_Object_Type::Nil) {
  283. return arguments;
  284. }
  285. Lisp_Object* evaluated_arguments = Memory::create_lisp_object_pair(nullptr, nullptr);
  286. Lisp_Object* evaluated_arguments_head = evaluated_arguments;
  287. Lisp_Object* current_head = arguments;
  288. while (current_head->type == Lisp_Object_Type::Pair) {
  289. try {
  290. evaluated_arguments_head->value.pair->first =
  291. eval_expr(current_head->value.pair->first, env);
  292. }
  293. current_head = current_head->value.pair->rest;
  294. if (current_head->type == Lisp_Object_Type::Pair) {
  295. evaluated_arguments_head->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr);
  296. evaluated_arguments_head = evaluated_arguments_head->value.pair->rest;
  297. } else if (current_head->type == Lisp_Object_Type::Nil) {
  298. evaluated_arguments_head->value.pair->rest = current_head;
  299. } else {
  300. create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation);
  301. return nullptr;
  302. }
  303. ++my_out_arguments_length;
  304. }
  305. *(out_arguments_length) = my_out_arguments_length;
  306. return evaluated_arguments;
  307. }
  308. proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  309. #define report_error(_type) { \
  310. create_error(_type, node->sourceCodeLocation); \
  311. return nullptr; \
  312. }
  313. if (error)
  314. return nullptr;
  315. switch (node->type) {
  316. case Lisp_Object_Type::T:
  317. case Lisp_Object_Type::Nil:
  318. return node;
  319. case Lisp_Object_Type::Symbol: {
  320. Lisp_Object* symbol;
  321. try {
  322. symbol = lookup_symbol(node, env);
  323. }
  324. return symbol;
  325. }
  326. case Lisp_Object_Type::Number:
  327. case Lisp_Object_Type::Keyword:
  328. case Lisp_Object_Type::String:
  329. return node;
  330. case Lisp_Object_Type::Pair: {
  331. Lisp_Object* lispOperator;
  332. if (node->value.pair->first->type != Lisp_Object_Type::CFunction &&
  333. node->value.pair->first->type != Lisp_Object_Type::Function)
  334. {
  335. try {
  336. lispOperator = eval_expr(node->value.pair->first, env);
  337. }
  338. } else {
  339. lispOperator = node->value.pair->first;
  340. }
  341. Lisp_Object* arguments = node->value.pair->rest;
  342. int arguments_length;
  343. // check for c function
  344. if (lispOperator->type == Lisp_Object_Type::CFunction) {
  345. Lisp_Object* result = lispOperator->value.cfunction->function(arguments, env);
  346. return result;
  347. }
  348. // check for lisp function
  349. if (lispOperator->type == Lisp_Object_Type::Function) {
  350. // only for lambdas we evaluate the arguments before
  351. // apllying
  352. if (lispOperator->value.function->type == Function_Type::Lambda) {
  353. try {
  354. arguments = eval_arguments(arguments, env, &arguments_length);
  355. }
  356. }
  357. Lisp_Object* result;
  358. try {
  359. result = apply_arguments_to_function(arguments, lispOperator->value.function);
  360. }
  361. return result;
  362. }
  363. }
  364. default: {
  365. report_error(Error_Type::Not_A_Function);
  366. }
  367. }
  368. #undef report_error
  369. }
  370. proc is_truthy (Lisp_Object* expression, Environment* env) -> bool {
  371. Lisp_Object* result;
  372. try {
  373. result = eval_expr(expression, env);
  374. }
  375. if (result->type == Lisp_Object_Type::Nil)
  376. return false;
  377. return true;
  378. }
  379. proc interprete_file (char* file_name) -> Lisp_Object* {
  380. Memory::init();
  381. Environment* env = Memory::create_empty_environment();
  382. Parser::init(env);
  383. char* file_content = read_entire_file(file_name);
  384. if (!file_content) {
  385. create_error(Error_Type::Unknown_Error, nullptr);
  386. }
  387. load_built_ins_into_environment(env);
  388. try {
  389. built_in_load("pre.slime", env);
  390. }
  391. Lisp_Object_Array_List* program;
  392. try {
  393. program = Parser::parse_program(file_name, file_content);
  394. }
  395. Lisp_Object* result = Memory::create_lisp_object_nil();
  396. for (int i = 0; i < program->next_index; ++i) {
  397. try {
  398. result = eval_expr(program->data[i], env);
  399. }
  400. }
  401. return result;
  402. }
  403. proc interprete_stdin() -> void {
  404. Memory::init();
  405. Environment* env = Memory::create_built_ins_environment();
  406. Parser::init(env);
  407. printf("Welcome to the lispy interpreter.\n");
  408. char* line;
  409. built_in_load("pre.slime", env);
  410. built_in_load("test.slime", env);
  411. if (error) {
  412. log_error();
  413. delete_error();
  414. }
  415. Lisp_Object* parsed, * evaluated;
  416. while (true) {
  417. printf(">");
  418. line = read_expression();
  419. parsed = Parser::parse_single_expression(line);
  420. if (error) {
  421. log_error();
  422. delete_error();
  423. continue;
  424. }
  425. evaluated = eval_expr(parsed, env);
  426. if (error) {
  427. log_error();
  428. delete_error();
  429. continue;
  430. }
  431. print(evaluated);
  432. printf("\n");
  433. }
  434. }