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

88 строки
2.8 KiB

  1. proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> void {
  2. // NOTE(Felix): right now we are simply adding the symol at the
  3. // back of the list without checking if it already exists but are
  4. // also searching for thesymbol from the back, so we will find the
  5. // latest defined one first, but a bit messy. Later we should use
  6. // a hashmap here. @refactor
  7. if (env->next_index == env->capacity) {
  8. env->capacity *= 2;
  9. env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
  10. env->values = (Lisp_Object**)realloc(env->values, env->capacity * sizeof(Lisp_Object*));
  11. }
  12. env->keys [env->next_index] = Memory::get_c_str(symbol->value.identifier);
  13. env->values[env->next_index] = value;
  14. ++env->next_index;
  15. }
  16. proc lookup_symbol_in_this_envt(String* identifier, Environment* env) -> Lisp_Object* {
  17. for (int i = env->next_index - 1; i >= 0; --i)
  18. if (string_equal(env->keys[i], Memory::get_c_str(identifier)))
  19. return env->values[i];
  20. return nullptr;
  21. }
  22. proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  23. // first check current environment
  24. String* identifier = node->value.identifier;
  25. Lisp_Object* result;
  26. result = lookup_symbol_in_this_envt(identifier, env);
  27. if (result)
  28. return result;
  29. for (int i = 0; i < env->parents->next_index; ++i) {
  30. result = try_lookup_symbol(node, env->parents->data[i]);
  31. if (result)
  32. return result;
  33. }
  34. if (string_equal(Memory::get_c_str(identifier), "nil")) {
  35. return Memory::nil;
  36. }
  37. if (string_equal(Memory::get_c_str(identifier), "t")) {
  38. return Memory::t;
  39. }
  40. return nullptr;
  41. }
  42. proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  43. Lisp_Object* result = try_lookup_symbol(node, env);
  44. if (result)
  45. return result;
  46. String* identifier = node->value.identifier;
  47. create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data);
  48. print_environment(env);
  49. return nullptr;
  50. }
  51. proc print_indent(int indent) -> void {
  52. for (int i = 0; i < indent; ++i) {
  53. printf(" ");
  54. }
  55. }
  56. proc print_environment_indent(Environment* env, int indent) -> void {
  57. for (int i = 0; i < env->next_index; ++i) {
  58. print_indent(indent);
  59. print(env->values[i]);
  60. printf(" %s", env->keys[i]);
  61. puts("");
  62. }
  63. for (int i = 0; i < env->parents->next_index; ++i) {
  64. print_indent(indent);
  65. printf("parent (%lld)", (long long)env->parents->data[i]);
  66. puts(":");
  67. print_environment_indent(env->parents->data[i], indent+4);
  68. }
  69. }
  70. proc print_environment(Environment* env) -> void {
  71. printf("\n=== Environment ===\n");
  72. print_environment_indent(env, 0);
  73. }