您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

523 行
20 KiB

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