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

116 строки
3.6 KiB

  1. proc define_symbol(Lisp_Object* symbol, Lisp_Object* value) -> 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. Environment* env = get_current_environment();
  8. if (env->next_index == env->capacity) {
  9. env->capacity *= 2;
  10. env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*));
  11. env->values = (Lisp_Object**)realloc(env->values, env->capacity * sizeof(Lisp_Object*));
  12. }
  13. env->keys [env->next_index] = Memory::get_c_str(symbol->value.symbol.identifier);
  14. env->values[env->next_index] = value;
  15. ++env->next_index;
  16. }
  17. proc lookup_symbol_in_this_envt(String* identifier, Environment* env) -> Lisp_Object* {
  18. for (int i = env->next_index - 1; i >= 0; --i)
  19. if (string_equal(env->keys[i], Memory::get_c_str(identifier)))
  20. return env->values[i];
  21. return nullptr;
  22. }
  23. proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  24. // first check current environment
  25. String* identifier = node->value.symbol.identifier;
  26. Lisp_Object* result;
  27. result = lookup_symbol_in_this_envt(identifier, env);
  28. if (result)
  29. return result;
  30. for (int i = 0; i < env->parents->next_index; ++i) {
  31. result = try_lookup_symbol(node, env->parents->data[i]);
  32. if (result)
  33. return result;
  34. }
  35. if (string_equal(Memory::get_c_str(identifier), "nil")) {
  36. return Memory::nil;
  37. }
  38. if (string_equal(Memory::get_c_str(identifier), "t")) {
  39. return Memory::t;
  40. }
  41. return nullptr;
  42. }
  43. inline proc push_environment(Environment* env) -> void {
  44. using namespace Globals::Current_Execution;
  45. append_to_array_list(envi_stack, env);
  46. }
  47. inline proc pop_environment() -> void {
  48. using namespace Globals::Current_Execution;
  49. --envi_stack->next_index;
  50. }
  51. inline proc get_root_environment() -> Environment* {
  52. using namespace Globals::Current_Execution;
  53. return envi_stack->data[0];
  54. }
  55. inline proc get_current_environment() -> Environment* {
  56. using namespace Globals::Current_Execution;
  57. return envi_stack->data[envi_stack->next_index-1];
  58. }
  59. proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* {
  60. Lisp_Object* result = try_lookup_symbol(node, env);
  61. if (result)
  62. return result;
  63. String* identifier = node->value.symbol.identifier;
  64. create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data);
  65. print_environment(env);
  66. return nullptr;
  67. }
  68. proc print_indent(int indent) -> void {
  69. for (int i = 0; i < indent; ++i) {
  70. printf(" ");
  71. }
  72. }
  73. proc print_environment_indent(Environment* env, int indent) -> void {
  74. if(env == get_root_environment()) {
  75. print_indent(indent);
  76. printf("[built-ins]-Environment (%lld)\n", (long long)env);
  77. return;
  78. }
  79. for (int i = 0; i < env->next_index; ++i) {
  80. print_indent(indent);
  81. print(env->values[i]);
  82. printf(" %s", env->keys[i]);
  83. printf(" (%lld)", (long long)env->values[i]);
  84. puts("");
  85. }
  86. for (int i = 0; i < env->parents->next_index; ++i) {
  87. print_indent(indent);
  88. printf("parent (%lld)", (long long)env->parents->data[i]);
  89. puts(":");
  90. print_environment_indent(env->parents->data[i], indent+4);
  91. }
  92. }
  93. proc print_environment(Environment* env) -> void {
  94. printf("\n=== Environment === (%lld)\n", (long long)env);
  95. print_environment_indent(env, 0);
  96. }