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

445 строки
16 KiB

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